• Rails 4 русские символы в базе вызывают ошибку?

    viktorvsk
    @viktorvsk
    Поправьте, если не прав. Вы считаете, что уже как минимум 2 года никто не разрабатывает на Rails, сохраняя в базу кириллицу?
    Ответ написан
    9 комментариев
  • Как изучая технологию не стать ее заложником?

    viktorvsk
    @viktorvsk
    Учиться методом проб и ошибок - как делает человечество и наука уже тысячи лет, несмотря на любые достижения и периодические исключения - тоже ужасный способ развития. Однако, к сожалению, лучше еще не придумали.

    Начнем с того, что рельсы появились в 2004 году, когда все было по-другому. И довольно успешно развиваются и подстраиваются под современные требования, что бы там ни говорили.

    Ну, и собственно, фреймворки (рельсы, в частности) - это не вордпресс, поэтому навыки которые вы получите при работе с ним (фреймворком) будут более обширные. И даже если технология умерт (заметим, что руби появился в 1995, как и джава, а рельсы поддерживаются, например, гитхабом), то значния полученные в процессе (необходимые при работе с фреймворком) - запросто перейдут в другие технологии. На примере рельс, во многих случаях перейдут как бест-практисес.

    Короче, самый нормальный путь обучения - на реальных задачах. Сегодня, по крайней мере, все реальные серьезные задачи (не берем редкие исключения типа ФБ и ВК, где тоже можно было бы не городить, кстати) делаются на фреймворках. Вывод: шашечки или ехать?
    Ответ написан
    Комментировать
  • Как сделать автономную работу парсера?

    viktorvsk
    @viktorvsk
    Ответ написан
    Комментировать
  • Как разделить программистов на категории (jun/mid/senior)?

    viktorvsk
    @viktorvsk
    То есть, у вас есть проект, который несколько лет нормально держится на 8 разработчиках и тут вы хотите некоторых из них потерять, некоторым дать повод искать новую работу, а некоторым просто уменьшить желание работать?
    Ответ написан
    6 комментариев
  • Ценится ли IT-специалист, который умеет все?

    viktorvsk
    @viktorvsk
    Работодатель ценит того, кто умеет решать его задачу в поставленных сроках с адекватными ресурсами.
    Если вы умеете вышивать крестиком, то работая в айти конторе вам это врядли поможет.

    Другое дело, что разнонравленное развитие - это хорошо во всех областях знаний. Синергия, как любят говорить манагеры и маркетологи. Наука только благодаря этому и работает.

    Плюс, конечно, если вы знаете много разного и умеете между этим переключаться, то понижается ваш шанс остаться невостребованным рынком.

    Хороший специалист в вебе должен знать от устройства основных протоколов, особенностей баз данных, разницы между языками в своей сфере, ключевые особенности популярных фреймворков и состояние рынка предложения в своей сфере.

    Сегодня очень много людей помешаны на стартапах. Не у всех из них много ресурсов. Если вы можете за неделю состряпать прототип его бизнес логики, сделать дизайн, от которого не будет тошнить, в нем можно будет разобраться, еще и сносно открыть на мобильнике. После - вы арендуете ему сервер под его нужны (shared, vps, vds, collocation) и сможете его настроить и задеплоить в продакшн, а через какое-то время еще и сделать на phone gap тормозящий аналог результирующего приложения - он явно отдаст вам предпочтение перед толпой компаний со штатом по 10 человек на проект, из которых 2 - менеджеры, и 1 эйчар

    P.S. да и вообще хрень это всё. Начнете реально шарить, поймете, что вся разработка связана и как-минимум все составляющие веба (если в нем работаете больше) будете знать несмотря на специализацию. А со временем придет понимание и смежных областей - мобильные, десктоп, микроконтроллеры, компутер сайенс и т.д.
    Ответ написан
    Комментировать
  • Как правильно разбить it скиллы по категориям ?

    viktorvsk
    @viktorvsk
    Обычно, разбивают классификацию на подгруппы:
    - По типу интерпретации\комиляции языка
    - По платформе использования
    - По виду хранения записей в базе данных
    - По среднему урвоню зарплат
    - По среднестатическому-годовому размеру команд на энтерпрайзах

    То есть, не просто "классификация по...", а как пишут в учебниках: "Классификация по типу виртулацизации бывает...". А там уже скилы, связанные с каждой, например

    Хотя вообще, полезность идеи сомнительна, имхо
    Ответ написан
    2 комментария
  • Как организовать работу программистов в стартапе если ты не программист?

    viktorvsk
    @viktorvsk
    1) Ваше понимание общей архитектуры - отстой (ознакомьтесь хотя бы с терминами, что бы не писать такие вещи)
    2) Ваше понимание об инструментах реализации - отстой (проекты делаются не инструментами, а разработчиками. А разработчики порой знают одни инструменты и совершенно не знакомы с другими. И в то же время остаются гениальными)
    3) Ваше понимание управления проектами - отстой (управленческая деятельность вообще показательна в плане того, что без практики от теории толк только отрицательный)
    4) Ваше желание распараллелить процесс старо как мир и само по себе не работает (почитайте Мифический человеко-месяц)
    5) Ваше желание оставить все в тайне (даже от разработчиков? :) ) - отстой. С ним более-менее успешно справляется разве что майкрософт.
    6) Идеи сами по себе - отстой, ничего не стоящие.
    7) Ваше желание выучить программирование ради проекта - не работает.

    Что делать, если есть непреодолимое желание замутить проект исходя из личной идеи (продиктованной рынком или нет? ... неординарная мысль в наше время, неправда ли?):
    1) Заразить своей идеей технически грамотного человека, которому вы сможете доверять процентов, эдак, на 99. И доверить техническу сторону ему.
    2) Найти инвестора, который по счастливой случайности не заметит, что вы не знаете, как нужно работать, взять у него денег и нанять менеджера, который знает, что делать и кому сколько платить.

    P.S. Разработка ПО - настолько широкая тема, что за более чем 40 лет серьезного коммерческого применения даже самые базовые части процесса не могут быть формализованы и решены универсально.

    Нельзя сказать, что нужно делать. Можно сказать, какой путь вероятнее всего будет предпочтительнее в данном конкретном случае (задача + контекст + команда + ресурсы).
    Ответ написан
    Комментировать
  • У кого есть опыть разработки под TecDoc?

    viktorvsk
    @viktorvsk
    Работал с parts-soft.ru
    Правда, проекты на рельсах
    Ответ написан
    Комментировать
  • Как правильно организовать архитектуру?

    viktorvsk
    @viktorvsk
    Если новости, анонсы и объявления у вас - сущности схожие, то создайте модель Контента и используйте STI
    Ответ написан
    Комментировать
  • Какая архитектура mysql необходима для создания простой социальной сети?

    viktorvsk
    @viktorvsk
    Взять и создать. Главное, правильно. И побезопаснее. Ну, с лайками можно не очень безопасно. А вот с друзьям - очень безопасно! И, главное, со всеми правильно это сделать!
    Ответ написан
    Комментировать
  • Как правильно сделать nested форму на другой view и использовать другой контроллер?

    viktorvsk
    @viktorvsk
    Ничего не понятно. Может, все же у поста нестет аттрибутс?
    И почему форма поста должна сабмитить на ревью? Проверяли вообще, туда ли идет запрос? И видимо ревью у вас без айдишника передается...
    А если поста с айди 41 нет, то его и не будет

    Сейчас такое ощущение, что у вас сайт отзывов, на котором к каждому отзыву можно привязать пост
    Ответ написан
  • В чем ошибка в ruby?

    viktorvsk
    @viktorvsk
    Видимо, что-то не так в регулярном выражении /-?/\d+/
    Надо понять, что вам нужно в нем получить и написать правильно.
    Проверять удобно здесь: rubular.com
    Ответ написан
  • Как при помощи php подключится к api vkontaket?

    viktorvsk
    @viktorvsk
    А на документацию аллергия?
    Тогда так:
    <?php
    /*
     * Class Vk
     * author: Dmitriy Nyashkin
     */
    class Vk{
    
        const API_VERSION = '5.24';
    
        const CALLBACK_BLANK = 'https://oauth.vk.com/blank.html';
        const AUTHORIZE_URL = 'https://oauth.vk.com/authorize?client_id={client_id}&scope={scope}&redirect_uri={redirect_uri}&display={display}&v=5.24&response_type={response_type}';
        const GET_TOKEN_URL = 'https://oauth.vk.com/access_token?client_id={client_id}&client_secret={client_secret}&code={code}&redirect_uri={redirect_uri}';
        const METHOD_URL = 'https://api.vk.com/method/';
        
        
        public $secret_key = null;
        public $scope = array();
        public $client_id = null;
        public $access_token = null;
        public $owner_id = 0;
    
        /**
         * Это Конструктор (Кэп.)
         * Передаются параметры настроек
         * @param array $options
         */
        function __construct($options = array()){
    
            $this->scope[]='offline';
    
            if(count($options) > 0){
                foreach($options as $key => $value){
                    if($key == 'scope' && is_string($value)){
                        $_scope = explode(',', $value);
                        $this->scope = array_merge($this->scope, $_scope);
                    } else {
                        $this->$key = $value;
                    }
    
                }
            }
        }
    
        /**
         * Выполнение вызова Api метода
         * @param string $method - метод, http://vk.com/dev/methods
         * @param array $vars - параметры метода
         * @return array - выводит массив данных или ошибку (но тоже в массиве)
         */
        function api($method = '', $vars = array()){
            
            $vars['v'] = self::API_VERSION;
            
            $params = http_build_query($vars);
    
            $url = $this->http_build_query($method, $params);
    
            return (array)$this->call($url);
        }
    
    
        /**
         * Построение конечного URI для выхова
         * @param $method
         * @param string $params
         * @return string
         */
        private function http_build_query($method, $params = ''){
            return  self::METHOD_URL . $method . '?' . $params.'&access_token=' . $this->access_token;
        }
    
        /**
         * Получить ссылка на запрос прав доступа
         *
         * @param string $type тип ответа (code - одноразовый код авторизации , token - готовый access token)
         * @return mixed
         */
        public function get_code_token($type="code"){
    
            $url = self::AUTHORIZE_URL;
    
            $scope = implode(',', $this->scope);
    
            $url = str_replace('{client_id}', $this->client_id, $url);
            $url = str_replace('{scope}', $scope, $url);
            $url = str_replace('{redirect_uri}', self::CALLBACK_BLANK, $url);
            $url = str_replace('{display}', 'page', $url);
            $url = str_replace('{response_type}', $type, $url);
    
            return $url;
    
        }
    
        public function get_token($code){
    
            $url = self::GET_TOKEN_URL;
            $url = str_replace('{code}', $code, $url);
            $url = str_replace('{client_id}', $this->client_id, $url);
            $url = str_replace('{client_secret}', $this->secret_key, $url);
            $url = str_replace('{redirect_uri}', self::CALLBACK_BLANK, $url);
    
            return $this->call($url);
        }
    
        function call($url = ''){
    
            if(function_exists('curl_init')) $json = $this->curl_post($url); else $json = file_get_contents($url);
    
            $json = json_decode($json, true);
    
            if(isset($json['response'])) return $json['response'];
    
            return $json;
        }
    
        // @deprecated
        private function curl_get($url)
        {
            if(!function_exists('curl_init')) return false;
    
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $tmp = curl_exec ($ch);
            curl_close ($ch);
            $tmp = preg_replace('/(?s)<meta http-equiv="Expires"[^>]*>/i', '', $tmp);
            return $tmp;
        }
    
        private function curl_post($url){
    
            if(!function_exists('curl_init')) return false;
    
            $param = parse_url($url);
    
            if( $curl = curl_init() ) {
    
                curl_setopt($curl, CURLOPT_URL, $param['scheme'].'://'.$param['host'].$param['path']);
                curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
                curl_setopt($curl, CURLOPT_POST, true);
                curl_setopt($curl, CURLOPT_POSTFIELDS, $param['query']);
                $out = curl_exec($curl);
    
                curl_close($curl);
    
                return $out;
            }
    
            return false;
        }
        /**
         * @param array $options
         */
        public function set_options($options = array()){
    
            if(count($options) > 0){
                foreach($options as $key => $value){
                    if($key == 'scope' && is_string($value)){
                        $_scope = explode(',', $value);
                        $this->scope = array_merge($this->scope, $_scope);
                    } else {
                        $this->$key = $value;
                    }
    
                }
            }
    
        }
    
        /**
         * @param bool $gid
         * @param array $files
         * @return array|bool
         */
        function upload_photo($gid = false, $files = array()){
    
            if(count($files) == 0) return false;
            if(!function_exists('curl_init')) return false;
    
            $data_json = $this->api('photos.getWallUploadServer', array('group_id'=> intval($gid)));
    
            if(!isset($data_json['upload_url'])) return false;
    
            $temp = array_chunk($files, 4);
    
            $files = array();
            $attachments = array();
    
            foreach ($temp[0] as $key => $data) {
                $path = realpath($data);
    
                if($path){
                  $files['file' . ($key+1)] = (class_exists('CURLFile', false)) ? new CURLFile(realpath($data)) : '@' . realpath($data);
                }
            }
    
            $upload_url = $data_json['upload_url'];
    
            $ch = curl_init($upload_url);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $files);
    
            $upload_data = json_decode(curl_exec($ch), true);
    
            $upload_data['group_id'] = intval($gid);
            
            $response = $this->api('photos.saveWallPhoto', $upload_data);
    
            if(count($response) > 0){
            
                foreach($response as $photo){
            
                    $attachments[] = $photo['id'];
                }
            }
            
            return $attachments;
    
        }
    
        /**
         * Заливка документа (например GIF файл)
         *
         * @param bool $gid
         * @param $file
         * @return bool|string
         */
        function upload_doc($gid = false, $file){
    
            if(!is_string($file)) return false;
            if(!function_exists('curl_init')) return false;
    
            $data_json = $this->api('docs.getUploadServer', array('gid'=> intval($gid)));
    
            var_dump($data_json);
    
            if(!isset($data_json['upload_url'])) return false;
    
            $attachment = false;
    
            $path = realpath($file);
    
            if(!$path) return false;
    
            $files['file'] = (class_exists('CURLFile', false)) ? new CURLFile($file) : '@' . $file;
    
            $upload_url = $data_json['upload_url'];
    
            $ch = curl_init($upload_url);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $files);
    
            $upload_data = json_decode(curl_exec($ch), true);
    
            $response = $this->api('docs.save', $upload_data);
    
            if(count($response) > 0){
    
                foreach($response as $photo){
    
                    $attachment = 'doc'.$photo['owner_id'].'_'.$photo['did'];
                }
            }
    
            return $attachment;
    
        }
    
        /**
         *
         * Заливка видео
         *
         * http://vk.com/dev/video.save
         *
         * @param array $options
         * @param bool $file
         * @return bool|string
         */
        function upload_video($options = array(), $file = false){
    
            if(!is_array($options)) return false;
            if(!function_exists('curl_init')) return false;
    
            $data_json = $this->api('video.save', $options);
    
            if(!isset($data_json['upload_url'])) return false;
    
            $attachment = 'video'.$data_json['owner_id'].'_'.$data_json['vid'];
    
            $upload_url = $data_json['upload_url'];
            $ch = curl_init($upload_url);
    
            curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
    
            // если указан файл то заливаем его отправкой POST переменной video_file
            if($file && file_exists($file)){
                //@todo надо протестировать заливку
                $path = realpath($file);
    
                if(!$path) return false;
    
                $files['video_file'] = (class_exists('CURLFile', false)) ? new CURLFile($file) : '@' . $file;
    
                curl_setopt($ch, CURLOPT_POSTFIELDS, $files);
                curl_exec($ch);
    
            // иначе просто обращаемся по адресу (ну надо так!)
            } else {
    
                curl_exec($ch);
            }
    
            return $attachment;
    
        }
    
    }
    Ответ написан
    8 комментариев
  • Каким онлайн-сервисом воспользоваться для для создания минимальной ИТ-инфраструктуры маленькой компании?

    viktorvsk
    @viktorvsk
    Видимо, Вам нужно что-то типа конструктора.
    ru.wix.com вот, вроде как, один из наиболее популярных
    Ответ написан
    Комментировать
  • Как сделать на сайте всплывающе окно с видеороликом?

    viktorvsk
    @viktorvsk
    Прикрутить вот это, например: dimsemenov.com/plugins/magnific-popup
    Ответ написан
    Комментировать
  • Какой движок выбрать для многофункционального портала?

    viktorvsk
    @viktorvsk
    Хотите что-то стоящее, долговечное, расширяемое и перспективное - забудьте про движки и цэмээски при таких запросах.

    Наймите одного человека, который поможет вам (заказчику) составить грамотное ТЗ и примерные стеки технологий, на которых это можно решить.

    Попробуйте найти человека, который возьмется это сделать. Изучите предложения, стеки и доводы за\против каждого из них.

    Разбивайте работу на мелкие, но логически завершенные этапы, что бы минимизировать риски. Желательно сделать так, что б уже первые части могли быть бизнес-ориентированы и полезны (приносить доход, работать на сео\рекламу\раскрутку\"интригу"\беплатную версию или доказать\опровергнуть пруф-оф-концепт)

    Не связывайтесь с агенствами.

    Будьте готовые потратить до полугода времени. Платить от 5 долларов в час хотя бы. Подумайте о рисках минимум х1.5.

    Ну, это если хотите реально, а не абы-как и чисто поиграться. А в итоге забросить или вернуться в самое начало.

    Прочел, что сложности с пунктами 7-10.

    7) Запретить скачивать эксель - легко. Запретить парсер - сложно, долго, дорого. ГЛУПО.

    8) Парсить легко. Сложно - обходить ограничения и блокировки, если они есть (не все этим страдают). Тут не ждите универсального решения. Даже если кто-то сделает решение, которое будет работать весь срок договора - то когда-то оно таки отвалится и, возможно, придется делать заново.

    9) Скрыть номер от одной категории и разрешить другой - легко. Онлайн оплата - легко до тех пор, пока вы работаете с нормальными платежными шлюзами.

    10) Платная регистрация - опять же, зависит от шлюза и степени "критичности". Например, если сделки на миллионы -будет дорого, если цена ошибки (взлома, утечки) не так велика - то не проблема. С партнерской программой - очень широкий вопрос. Но по факту тоже, особенности только в платежном шлюзе (способе)
    Ответ написан
    Комментировать
  • Как быстро записываются данные?

    viktorvsk
    @viktorvsk
    Данные записываются очень быстро. Так быстро, что обычно их прочесть не успеваешь, а они уже записались. Сделать этот процесс можно быстрее если: 1) уменьшить количество данных, 2) увеличить мощность вычислительных средств
    Ответ написан
    Комментировать
  • Почему Devise не авторизует пользователя?

    viktorvsk
    @viktorvsk
    Вы скинули лог вебсервера. Разве девайс по-дефолту не рендерит все актив-рекорд ошибки?
    Ответ написан