четверг, 21 ноября 2013 г.

Несколько слов о загрузке файлов с помощью Resumable.js

На днях познакомился с javascript-плагином для загрузки файлов Resumable.js и его код на GitHub-e. Вот появились некоторые соображения по поводу загрузки файлов.

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

Мне кажется, что при загрузке файлов есть несколько интересных вопросов. Один из таких вопросов это загрузка файлов большого размера (больше 2 ГигаБайт). Пишут, что у браузеров есть ограничения на размер загружаемых файлов.

Используя стандартный способ загрузки в HTML '<input type="file">' (php-пример)  пользователь, который загружает большой файл, должен ждать долгое время. Для него не понятно, насколько реально загружен файл, будет ли удачной загрузка, возникнут ли ошибок при загрузке, придется ли начинать загрузку заново. С появлением HTML5 FILE API (пример) можно решить эту проблему, реализовав возможность возобновлять загрузку файлов с того состояние, в котором они были прерваны, а не начинать все с самого начала. Такая возможность есть и у Resumable.js. Есть ограничения на браузеры, в которых доступна эта возможность (Firefox 4+ и Chrome 11+).

Общая идея о том, как это реализовано. Resumable.js разбивает файл на несколько небольших фрагментов (chunk), используя HTML5 FILE API.  Затем каждый фрагмент загружается по одному, пока весь файл не будет загружен. Если какой-то из фрагментов файла невозможно загрузить правильно, то этот фрагмент будет загружен повторно.

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

Продолжение следует =)

четверг, 7 ноября 2013 г.

Zip и Unzip файлов в Ubuntu

Столкнулся с простой задачей, нужно создать zip-архив и нужно распаковать zip-архив под Ubuntu.

Решение было быстро найдено в Google. Здесь основные команды, что бы не забыть.

Установка архиватора

По умолчанию в Ubuntu не установлены zip/unzip инструменты, поэтому их нужно установить:

# sudo apt-get install zip
# sudo apt-get install unzip
или

# sudo apt-get install zip unzip
Работа с архивами

Для создания архива data.zip из всех файлов в текущей директории, т.е. взять все файлы из текущей директории, где вы сейчас находитесь, сжать их и положить в архив data.zip, нужно выполнить следующую команду:

# zip data *
Замечание: расширение .zip будет добавлено автоматически командой zip. Мы указываем только имя архива.

Если нужно добавить в архив не только все файлы в текущей директории, но и все поддиректории, то используем команду:
# zip -r data *
Вывести список всех файлов в архиве data.zip
# unzip -l data.zip
Извлечь все файлы и поддиректории из архива data.zip в текущую директорию:
# unzip data.zip
Извлечь из архива data.zip файл с именем index.html:
# unzip data.zip index.html
Извлечь из архива data.zip все файлы из директории /tmp:

четверг, 5 января 2012 г.

Передача переменных в Ruby.

Привет.
Вот на дворе уже и новый 2012 год. Поздравляю всех с этим событием. Конец СВЕТА отменили, поэтому продолжаем жить дальше и познавать что-то новое.

Для начала простой пример1.
Пусть есть 2 переменные: var1 и var2.
var1 = 'I am var1'
var2 = var1

Какие значения имеют var1 и var2?
Правильный ответ:
var1  #=>  'I am var1'
var2  #=>  'I am var1'

А теперь давайте сделаем так:
var1 = 'I am not var1'
Какие теперь значения имеют var1 и var2?

Правильный ответ:
var1  #=> 'I am not var1' 
var2  #=> 'I am var1'

У вас не возник вопрос почему?
Ответ прост: var2 никогда не была var1, а просто указывала на тот же объект, что и var1. Новым присваиванием мы изменили ссылку на объект на который указывает var1.

Теперь еще раз =)

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

Пример2:
a = "abcdefg"
b = a
b #=> "abcdefg"
a[3] = 'R'
b #=> "abcRefg"

то есть при изменении значения переменной a, неявно изменилось и значение b, так как они содержат ссылку на один объект.

Всех с наступающим Рождеством.
Удачи.

четверг, 22 сентября 2011 г.

Как дробные числа в целые превращались.

Не для кого не секрет, что математические операции с целыми числами более быстрее, чем с вещественными числами, т.е. использовать int быстрее, чем float, double и т.д.

Недавно увидел такой подход в программировании. Для более быстрых вычисление вещественные числа переводили в целые и уже работали с ними, а потом для получения требуемого результата опять преобразовывали обратно.

Идею этого подхода можно наглядно показать на примере квантования.
В общем виде квантование это процедура построения чего-либо с помощью дискретного набора величин, например, целых чисел, в отличие от построения с помощью непрерывного набора величин, например, вещественных чисел.

Проще говоря: у нас есть исходное число (T = 3.5), мы выбираем минимальное число, которым будим дробить (измерять) исходное число (h=0.1). Теперь преобразуем исходное число в новое целое число, используя минимальное число (i=T/h=3.5/0.1=35).

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

Основной минус бросается в глаза сразу, если h=0.3, а T=3.5, то i = 11.666, что не соответствует тому, о чем мы говорили выше. Выбираете h, как степень 10 (10^(-1) = 0.1 и т.д.).

Вот такой интересный подход. Говорят, что это позволило избавиться от многих ошибок с округлением. =)

Спасибо за внимание. 

среда, 21 сентября 2011 г.

Возвращение из отпуска

Привет, друзья.

После перерыва возвращаюсь к своим кратким постам.
Был в отпуске. Отдыхал вместе с друзьями. После этого собирался с мыслями и силами для новых публикаций. Накопилось много интересного, чем можно поделится и о чем можно рассказать.

Политика публикаций не изменится: 2 сообщения в неделю =)
Формат постов также не должна изменится: буду пытаться кратко и по делу рассказать о затронутой теме.

Всегда приветствуются ваши комментарии. Пишите.

До встречи.
Удачи. 

четверг, 11 августа 2011 г.

Делегирование в RubyOnRails (method delegate in RubyOnRails)


Всем привет!

Сегодня расскажу про метод delegate в RubyOnRails.

Его назначение: позволяет вызывать методы других объектов как свои собственные.

Использовать его просто:
delegate [один или несколько методов], to: => [целевой класс]

[один или несколько методов] - названия методов из целевого класса.
Имена методов записываются как символы или как строки. Несколько методов разделяются запятой.
Пример: :hello, :goodbye, :start, :end
[целевой класс] - название имени класса в который будут делегироваться запросы на вызов метода.
Пример кода:
Есть класс Greeter
class Greeter < ActiveRecord::Base
    def hello()   "hello"   end
    def goodbye() "goodbye" end
  end

Мы хотим в классе Foo делегировать вызов метода hello классу Greeter
  class Foo < ActiveRecord::Base
    belongs_to :greeter
    delegate :hello, :to => :greeter
  end

Тогда вызывая у объекта класса Foo метод hello получим:
  Foo.new.hello   # => "hello"

Если попытаемся вызвать другой метод класса Greeter - goodbye, то получим ошибку.
  Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>
Это только один из способов использования delegate.
Спасибо за внимание.
Удачи.

четверг, 28 июля 2011 г.

Термин "Утиная Типизация" (Duck Typing)

Привет.

Сегодня немного расскажу о понятии "утиная типизация" или просто "утипизация" в Ruby. Ссылка на wiki-ru и wiki-eng.
Термин принадлежит Дейву Томасу (Dave Thomas) и восходит к поговорке: если что-то выглядит как утка, плавает как утка и крякает как утка, то, вероятно, это утка. (If it looks like a duck, swims like a duck and quacks like a duck, then it probably is a duck.).
Точный смысл термина "утипизация" - тема для отдельных дискуссий, скорее всего это намек на тенденцию Ruby заботиться не сколько о точном классе объекта, сколько о том, какие методы для него можно вызвать и какие операции над ним можно выполнять. Таким образом, обычным делом становится просто передать объект методу, зная, что при неправильном использовании будет выброшено исключение (exception).
Утиная типизация решает некоторые проблемы иерархической типизации:
  • невозможность явно указать (путем наследования) на совместимость интерфейса со всеми настоящими и будущими интерфейсами, с которыми он идейно совместим;
  • экспоненциальное увеличение числа связей в иерархии типов.

Подведем итоги: в обход наследованию, мы достигаем однообразности поведения объекта просто определив ему все метода интересующего нас интерфейса и все готово. Мы можем использовать такой объект думая, что он наследник определенного класса.

Как-то так. Всем спасибо за внимание.
До встречи.

пятница, 22 июля 2011 г.

Мысли об эталонной реализации.

Всем привет!

Первым делом конечно Wiki

А теперь мои мысли.

На днях сталкнулся с таким понятием как эталонной реализацией (от англ. reference implementation). Первый мысли были, что это какая-то абстрактная модель для построения всего и все. А вот и нет, оказалось, что за термином кроется реализация программного обеспечения, полностью соответствующая спецификации, либо демонстрация спецификации в действии.

Для чего все это? - первый вопрос, который у меня возник.
Оказывается цель всего этого помочь другим разработчикам реализовать их собственные версии спецификации или определить проблемы, возникающие во время разработки спецификации.

Характеристики эталонной реализации:
  1. Разработана одновременно со спецификацией и тестовым пакетом; 
  2. Демонстрирует, что спецификация реализуема; 
  3. Служит образцом при тестировании других реализаций тестовым пакетом; 
  4. Служит «Золотым стандартом» при измерении других реализаций; 
  5. Улучшает наглядность спецификации, когда специально подготовленные тесты не подходят.
Таким образом можно прийти к выводу какой большой и тернистый путь должна пройти спецификация, что бы материализоваться и стать либо полноценной библиотекой либо новой веткой развития языка программирования.

вторник, 5 июля 2011 г.

Как проверить существование в хэше ключа (Ruby).

Привет.

Нам нужно быстро выполнить следующие действия.
Пусть есть  хэши:
hash1 = {:text => 'redf', :subtext => 'Her' }
hash2 = {:text => 'yels' }
Очется однобразно работать с этими хэшами, но в одном есть ключ subtext, а в другом нет.
Что делать?
Нужно проверить, есть ли нужный ключ в хэше и если он есть получить значение по этому ключу.
Это можно сделать используя try.
hash.try(:[], :subtext)
Если у hash есть ключ subtext, то получим значение по ключу, если ключа нет, то nil.
hash1.try(:[], :subtext) # Her
hash2.try(:[], :subtext) # nil

Вот так вот просто это делается в Ruby =)

Пока!!!

пятница, 10 июня 2011 г.

Rails и Heroku.

Привет.

Облачные технологии приходят на помощь всем.
Для разработчиков Ruby on Rails (RoR) есть такой сервис как Heroku. Heroku это PaaS.

Для чего он нужен?
В идеале данный сервис должен упростит процесс разработки и запуска проектов, использующих Ruby on Rails.

Что предлагает Heroku?
Первое предложение заключается в том, что предоставляется среда разработки проектов на RoR, для работы с которой вам понадобится лишь браузер.  Это избавляет от необходимости использования сторонних программных продуктов, предназначенных для программирования на RoR. Плюс этого в том, что в сравнении с другими языками, ограничения, накладываемые Ruby и RoR, могут быть сложнее, чем просто установка и настройка, использование предоставляемой среды разработки утраняет эти ограничения. Heroku хотят предоставить, как профессионалам, так и новичкам, возможность беспроблемной разработки с использованием лишь ПК с браузером.

Второе предложение Heroku позволяет разработчикам размещать (host) их, а так же масштабировать (scale). Heroku использует Amazon Web Services для масштабирования проектов размещающихся у них, и планируют в качестве дополнительной возможности взымать плату за кол-во потребляемых мощностей с платных пользователей, использующих данную услугу. Даже, если вы не желаете разрабатывать свое приложение с использованием Heroku, вы можете просто импортировать ваше приложение, чтобы ощутить всю мощь автоматической масштабируемости, предоставляемой этим сервисом.

Пробуйте.

Удачных выходных.

вторник, 7 июня 2011 г.

Как запомнить SQL JOINS.

Всем привет!

Для тех, кто забыл, а может и не знал как быстро запомнить различные JOIN, на помощь приходит вот такие картинки.
Источник




Все. =)
Удачи.

пятница, 3 июня 2011 г.

Типичный рабочий процесс при работе с SVN.


Привет.

Многие ипользуют различные системы контроля версий. У новичков всегда возникает вопрос, что делать и как комитеть, как работать с системой.

В документации по SVN представлен вот такой типичный рабочий процесс (Basic Work Cycle):
  1. Обновляем свою рабочую копию проекта.
    • svn update
  2. Добавляем свои изменения.
    • svn add
    • svn delete
    • svn copy
    • svn move
  3. Проверяем добавленные изменения на корректность.
    • svn status
    • svn diff
  4. Возможно отменяем некоторые изменения.
    • svn revert
  5. Устраняем (резолвим) конфликты / применяем (мержим) изменения от других.
    • svn update
    • svn resolve
  6. Коммитем свои изменения.
    • svn commit
    Это можно взять за основу своего рабочего процесса работы с системой контроля версии.

    Спасибо за внимание.
    Удачи.

    вторник, 31 мая 2011 г.

    Немного про array и метод map в Ruby

    В Ruby как и в других языках программирования есть массивы - класс Array.
    Этот класс (Array) имеет много методов для работы с массивами раскажу об одном из этих методов map.
    Поясню на примере:
    Пусть есть массив arr1 = [4, 5, 6]
    Мы можем создать новый массив arr2 на основе массива arr1 используя map.
    arr2 = arr1.map { |a| a+6 } # [10, 11, 12]
    Но есть особенность, мы хотим преобразовывать массив arr1 только для определенных элементов.
    Например вот так: arr2 = arr1.map { |a| a+6 if (a > 4) } # [nil, 11, 12]
    Как видно, если условие не выполнилось, то в новом массиве arr2 будут элементы nil. Для того, чтобы их не было можно воспользоваться методом compact.
    arr2 = arr1.map { |a| a+6 if (a > 4) }.compact # [11, 12]
    Во всех приведенных примерах методы map и compact создают ноые массивы.
    Кто хочет может подумать, как оптимизировать работу с памятью.

    Всем удачи.

    пятница, 27 мая 2011 г.

    Ключевые слова и идентификаторы в Ruby

    Привет. Вот и пятница.

    Сегодня в России официально начались продажи iPad2 =)

    Но ... Приступим.

    Ключевые (или зарезервированные) слова в Ruby обычно не применяются ни для каких иных целей. Вот их полный перечень, наверное =):
    • BEGIN 
    • END
    • alias
    • and
    • begin
    • break
    • case
    • class
    • def
    • defined?
    • do
    • else
    • elsif
    • end
    • ensure
    • false
    • for
    • if
    • in
    • module
    • next
    • nil
    • not
    • or
    • redo
    • rescue
    • retry-
    • return
    • self
    • super
    • then
    • true
    • undef
    • unless
    • until
    • when
    • while
    • yield
    Имена переменных и других идентификаторов обычно начинаются с букв или специального модификатора. Основные правила таковы:
    • имена локальных переменных (и таких псевдопеременных, как self и nil начинаются со строчной буквы или знака подчеркивания _;
    • имена глобальных переменных начинаются со знака доллара $;
    • имена переменных экземпляра (принадлежащих инстанцированному объекту)  начинаются с знака «собачки» @;
    • имена переменных класса (принадлежащих классу) предваряются двум: знаками @ (@@);
    • имена констант начинаются с прописной буквы;
    • в именах идентификаторов знак подчеркивания _ можно использовать наравне со строчными буквами;
    • имена специальных переменных, начинающиеся со знака доллара (например, $1 и $/), здесь не рассматриваются.
    Приведу некоторые примеры:
    • локальные переменные alpha, _ident, some_var;
    • псевдопеременные self, nil,__file__;
    • константы K6chip, Length, LENGTH;
    • переменные экземпляра @foobar, @thxll38, @not_const; 
    • переменные класса @@phydeaux, @@my_var, @@nOT_const;
    • глобальные переменные $beta, $B12vitamin, $not_CONst.
    На этом все.
    Удачи.

    вторник, 24 мая 2011 г.

    Концепция баррикады

    Всем доброго вторника!

    Захотелось поговорить о чем-то высоком, для этого блога это значит о проектировании и архитектуре ПО =)

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

    Суть концепции заключается в следующем:
    Все окружение программы разделяется на два - кому можно доверять (ближний круг) и кому нет (дальний круг).

    Ближнему кругу можно относиться спокойно, там нет (точнее не должно быть) неверных объектов и ошибок.

    Дальний круг полон сюрпризов, могут быть как хорошие, так и ошибочные объеты. К этому кругу нужно присмотреться и узнать, кто есть кто.

    Концепция баррикады предлагает провести черту между сущностями, отделив их друг от друга этаким барьером. Под «сущностями» можно подразумевать разные вещи. В зависимости от масштабов и архитектуры вашей системы, баррикада может проходить между методами класса, между классами, между отдельными модулями (библиотеками) и т.д.

    Часть сущностей (назовем их «забаррикадные») — живут в активной и агрессивной среде, взаимодействуют с внешним миром, вызываются сторонними классами и им может быть передана любая чушь. Начинаться они должны со всех необходимых проверок и никому не доверять. Невалидность входных данных должна рассматриваться как штатный режим работы. Он не должен валить программу. В зависимости от принятой в проекте идеологии, при приходе невалидных данных можно написать сообщение в лог, выдать сообщение пользователю или вообще молча исправить данные на валидные и продолжить работу.

    Следующая группа объектов — это сама «баррикада». Роль баррикады — гарантировать всем, кто находится внутри безопасность. Ничто не должно проникнуть внутрь баррикады непроверенным, несконвертированным во внутренние форматы, невалидным и т.д. Сюда входят разнообразные конверторы, валидаторы, вропперы и прочие аналогичные вещи.

    И последняя часть концепции — это «внутрибаррикадные» жители. Они и есть тем, ради чего вся эта затея начиналась. Метод, находящийся внутри баррикады может не проверять входные параметры или текущее состояние объекта, к которому он принадлежит! За него это уже гарантированно сделала баррикада. Во всех внутрибаррикадных методах обязаны стоять ASSERTы, поскольку невалидность чего-нибудь является уже не проблемой взаимодействия с внешней средой, а конкретной ошибкой в баррикаде. Её в дебаг-версии нужно обнаружить и исправить. А в релизе ASSERTы будут выброшены компилятором и не будут никому мешать.

    Конечно, в баррикадах есть недостатки — нужно чётко разграничивать вещи относительно баррикады по уровням доверия к ним, проверки внутри баррикады все-равно иногда нужны (ASSERTы), хоть их и значительно меньше. Всё это решает где-то полторы-две из трех описанных в начале статьи проблем, так что иногда может пригодиться.

    Вот такая вот концепция.

    Всем удачной недели.

    пятница, 20 мая 2011 г.

    Магические имена в Rails.

    Привет, друзья!

    Уже пятница и не загорами веселье, отдых и магия, но перейдем к тебе поста.

    В Ruby on Rails есть список магических слов (Magic Field Names), которые используются системой для определенных нужд. Использование таких же названий может привести к проблемам вида WARNING: Can't mass-assign protected attributes: type.

    Вот список этих зарезервированных слов и имен (List of Magic Field Names):
    • created_at
    • created_on
    • updated_at
    • updated_on
    • lock_version
    • type
    • id
    • #{table_name}_count
    • position
    • parent_id
    • lft
    • rgt
    • quote_value (is used for quoting)
    • template
    На этом все.
    Желаю всем приятных выходных.
    Удачи.

    понедельник, 16 мая 2011 г.

    Кое-что о Garbage Collector в Ruby

    Garbage Collection (GC) в Ruby отличается от сборщиков мусора в Java, C# и некоторых других языков программирования. И отличает его то, что в Ruby GC не generational, т.е. non-generational. Это значит, что GC в Ruby не делит объекты на поколения. Суть использование «поколений объектов» (GC в Java, к примеру) сводится к тому, что вновь созданные объекты гораздо чаще становятся недостижимыми, чем те объекты, время жизни которых велико (поколений объектов - штука сама по себе не простая). Соответственно, GC, который учитывает поколения, сильно сокращает время выполнения сборки мусора, посколько количество просматриваемых объектов в ходе сборки не так уж и велико, поскольку сборщик обращает внимание только на «молодое» поколение, будучи уверенный в том, что остальные поколения он на славу почистил (существуют и другие поведенческие модели, но эта — основная). Такое деление на поколения и называется generational GC. Таким образом, GC в Ruby очень дорогая операция, потому что ему приходится просматривать все объекты в памяти, каждый раз, когда GC будет вызван.

    В Ruby интересная модель управления памятью (How Ruby Manages Memory and Garbage Collection).


    На этом все.
    Удачной недели.


    четверг, 12 мая 2011 г.

    Технология cookie. Недостатки.

    Cookie, на русском говорят куки.
    Для начала вот какое определение. 
    Куки (от англ. cookie — печенье) — небольшой фрагмент данных, созданный веб-сервером или веб-страницей и хранимый на компьютере пользователя в виде файла, который веб-клиент (обычно веб-браузер) каждый раз пересылает веб-серверу в HTTP-запросе при попытке открыть страницу соответствующего сайта. Применяется для сохранения данных на стороне пользователя, на практике обычно используется для:
    - аутентификации пользователя;
    - хранения персональных предпочтений и настроек пользователя;
    - отслеживания состояния сессии доступа пользователя;
    - ведения статистики о пользователях.

    Это wiki_ru или можно на wiki_eng.

    При всей универсальности файлов cookie (они поддерживаются производителями браузеров с незапамятных времен), им присущи серьезные (с современной точки зрения) недостатки:
    - ограниченный, и очень маленький размер файлов. Обычно не более 4 Кбайт;
    - передача от браузера к серверу и обратно при каждом запросе;
    - проблем конфиденциальности;
    - технические недостатки. В частности, они не всегда точно идентифицируют пользователя и
      могут быть причиной атак злоумышленников;
    - если на компьютере используется более одного браузера, то, как правило, каждый имеет 
      отдельное хранилище для куки;
    - каждый сайт должен иметь свои собственные куки;
    - злоумышленник может изменить содержимое куки перед отправкой;
    - куки могут вызвать противоречия между клиентом и сервером.

    Можно отметить, что как развитие технологии cookie, обычно рассматривают Web Storage.

    Возвращение и обращение к читателям.

    Всем, Привет!
    Я вернулся. Прошел целый месяц, но время не прошло зря. Благодоря вашим отзывам и рекомендация от друзей сложилось более понимающее отношение к ведению блога.

    Кратко о том, что вас ждет.

    Во-первых про сами статьи.
    Статьи будут представлять собой описание чего-либо или решение какой-либо проблемы.
    Постораюсь быть как можно информативнее и кратким.

    Во-вторых про переодичность.
    Статьи будут выходить два раза в неделю. Скорее всего дни следующие: 1 раз - понедельник или вторник, 2 раз - четверг или пятница.

    Спасибо. До новых встреч.