понеділок, 31 грудня 2012 р.

Ретроспектива 2012



2012 рік добігає кінця. І за хорошою традицією в останньому записі я згадую найбільш значущі події в світі Ruby, що відбулися у цьому році.

Цього року формат статті зазнав деяких змін. Події розбиті по місяцях.

Січень
  • Випуск KidsRuby 1.0, редактора Ruby розробленого в освітніх цілях для дітей дошкільного й молодшого шкільного віку (але не менш корисного для дорослих). Він включає в себе навчальні посібники та графічну систему в стилі мови програмування Logo для більш наочного типу навчання.

Лютий

Березень
  • FXRuby - Ruby bindings для FOX (крос-платформної бібліотеки з відкритим вихідним кодом для побудови графічного інтерфейсу) повернувся з довгого періоду застою.
  •  Юкіхіро Мацумото (Yukihiro Matsumoto), автору мови програмування Ruby, присуджена премія "Free Software Awards 2011" номінації, що вручається за просування і розвиток вільного ПЗ.
  • Ruby став стандартом ISO.
    Після чотирьох років розробки, 31 березня цього року за результатами голосування Ruby версії 1.8 був прийнятий як стандарт ISO/IEC 30170. Будемо сподіватися, що наступну версію стандарту підготують швидше.
Квітень
  • mruby - полегшена реалізації мови Ruby, виконана за ISO стандартом для виконання різних середовищах. Може були як виконана інтерпретатором так і бути скомпільованою і виконаною віртуальною машиною,  відповідно до його модульної конструкції.
  • MobiRuby - інструментарій для створеня IOS додатків за допомогою мови Ruby. В майбутньому планується підтримка Android.
Травень
  • Компанія Red Hat запустила нову хмарну платформу OpenShift з підтримкою Java, Ruby, Node, Python, PHP і Perl.
  • Два ключових розробника команди JRuby(Thomas Enebo і Charles Nutter) переходять на роботу в Red Hat.
  • Перший попередній реліз JRuby 1.7. Цікавий тим, що це перший реліз з підтримкою  InvokeDynamic - рішення, що дозволяє взаємодіяти з динамічними мовами практично без втрати продуктивності.
  • Реліз RubyMotion - набір інструментів для IOS, який дозволяє швидко розробляти і тестувати власні програми для iPhone або iPad, за допомогою Ruby.
Червень
  • Вийшла ювілейна версія 1.0 бібліотеки R18n, яка дозволяє додати в додаток на Rails/Ruby підтримку декількох мов (i18n).
  • Реліз Sublime Text 2.0
Вересень

Жовтень
Листопад
Грудень
  • Heroku додали офіційну підтримку для JRuby

2013 рік обіцяє також бути багатим на нові релізи. Зокрема Ruby 2.0 і Rails 4.0.

Щиро вітаю Вас з наступаючим Новим Роком!
Нехай він принесе нам довгождане щастя, спокій, добробут, палке кохання, міцне здоров'я та здійснення наших самих заповітних мрій!

    пʼятницю, 28 грудня 2012 р.

    Історія одного тупняку, або як я конвертував DBF в SQLite3

    Нещодавно до мене потрапив файл у форматі dbf з досить цікавою інформацією. Але сьогодні не про це.

    Для роботи з цією інформацією, я вирішив імпортувати таблицю DBF у SQLite3. Використовувати сторонній софт для такої тривіальної задачки — це не наш варіант. Ми не шукаємо легких шляхів. Напишемо скрипт самі. Писати, звичайно, будемо на Ruby.

    DBF — застаріваючий формат зберігання даних, який (був?) широко розповсюджений на пострадянському просторі.

    Недовгі пошуки навели на бібліотеку dbf. Як описує її автор, це невелика швидка бібліотека для читання DBase, Xbase, Clipper і FoxPro файлів баз даних.

    Відкриваємо DBF файл:
    require 'dbf'
    dbf_table = DBF::Table.new(dbf_file, nil)
    dbf_columns = dbf_table.columns
    
    І відразу отримуємо помилку:
    dbf-2.0.3/lib/dbf/column/base.rb:19:in `initialize': column name cannot be empty (DBF::Column::NameError)
    

    Проблема виникає через те, що при ініціалізації поля, у його назві відсікаються всі не-ASCII символи. А такий порядок речей в моєму випадку недопустимий, оскільки
    імена полів у DBF таблиці записані кирилицею у кодуванні cp1251.

    Тут стане у нагоді "monkey patching".
    Ініціалізуємо таблицю у кодуванні cp1251 і конверуємо імена полів в utf-8:

    module DBF
      module Column
        class Base
          attr_reader :name, :type, :length, :decimal
    
          def initialize(name, type, length, decimal, version, encoding = nil)
            @name, @type, @length, @decimal, @version, @encoding = clean(name, encoding), type, length, decimal, version, encoding
    
            raise LengthError, "field length must be greater than 0" unless length > 0
            raise NameError, "column name cannot be empty" if @name.length == 0
          end
    
          def clean(value, encoding)
            value.force_encoding(encoding).encode('utf-8')
          end
    
        end
      end
    end
    
    dbf_table = DBF::Table.new(dbf_file, nil, 'cp1251')
    dbf_columns = dbf_table.columns
    

    Не вдаючись в подробиці створення схеми SQLite3 (повний код скрипта Ви знайдете в кінці статті), перейдемо відразу до імпорту. Задачка звичайно зовсім тривіальна і написання рішення займає лічені хвилини.
    dbf_table.each do |record|
      sqlite_db.execute("INSERT INTO the_table VALUES (?,?,?,?,?,?)", record.attributes.values)
    end
    
    Тут можна було б піти покурити, попити чаю або кави чи навіть подивитися фільм. Даний процес зайняв досить багато часу.
    Час роботи такого рішення мене не вдовольняв зовсім.
    Бувалі програмісти мабуть відразу зрозуміють де собака зарита. Але цей тупняк поглинув мене на кілька годин.
    Спочатку я грішив на повільність бібліотеки dbf. Але цей варіант був швидко відкинутий. Каменем спотикання була саме бібліотека SQLite3.
    Наступну годину я курив, пив пиво і дивився "Ruby Sparks". Між іншим красивий і милий романтичний фільм, але настирливий продакт-плейсмент Apple вже бісить. Паралельно ґвалтува ґуґл в пошуках рішення. І ось воно зійшло:
    sql_db.transaction do |db|
      dbf_table.each do |record|
        db.execute("INSERT INTO the_table VALUES (?,?,?,?,?,?)", record.attributes.values)
      end
    end
    

    Несподівано скрипт, який виконувався годинами, виконався за 10 секунд. Підвищення продуктивності over 9000%. Я отетерів(!) від такого результату.

    Мораль цієї історії проста... Комусь здається, що це тривіально, але мені просто хотілось поділитися з кимось цими думками.

    Нище ви знайдете повну версію скрипта для конвертування DBF у SQLite3.

    четвер, 27 грудня 2012 р.

    Робота з файлами eml в Ruby

    Сьогодні зіткнувся з проблемою пошуку вкладень серед багатьох файлів з розширенням eml.

    Формат eml використовується багатьма клієнтами електронної пошти, включаючи Microsoft Outlook Express, Windows Mail і Mozilla Thunderbird. Це звичайний текстовий файл у форматі MIME, що містять заголовки повідомлень електронної пошти, а також вміст повідомлення та вкладення.

    Відкрити його під Linux не складає труднощів, наприклад, за допомогою поштового клієнта KMail, однак таке рішення мені здалося занадто складним.

    Трохи погугливши, виявилося, що бібліотека email чудово вміє розбирати такі файли.

    В результаті вийшов невеликий скрипт, який вибирає всі файли з розширенням eml у поточній директорії, і відображає в консолі текстовий вміст листа, а прикріплені файли зберігає у відповідних директоріях.
    require 'mail'
    
    Dir.glob('*.eml') do |filename|
      mail = Mail.read(filename)
    
      puts <<EOF
      From:    #{mail.from}
      To:      #{mail.to}
      Subject: #{mail.subject}
      Date:    #{mail.date}
    
    EOF
    
      charset = mail.text_part.content_type_parameters['charset']
      puts mail.text_part.body.decoded.force_encoding(charset).encode('utf-8')
    
      if mail.multipart?
        dir = File.basename(filename, File.extname(filename))
        Dir.mkdir(dir) if !Dir.exists?(dir)
    
        mail.attachments.each do |attachment|
          file = File.open(dir + '/' + attachment.filename, 'wb') { |f| f.write attachment.body.decoded }
          puts "Saving `#{attachment.filename}`"
        end
      end
    
      puts "===\n\n"
    end
    

    понеділок, 29 жовтня 2012 р.

    Opal — реалізація Ruby на JavaScript

    Opal — реалізація Ruby, написана на мові JavaScript.

    Opal включає в себе компілятор (який можна запустити в будь-якому браузері), основну бібліотеку і середовища виконання. У стисненому вигляді основна бібліотека і середовище виконання займають всього-на-всього 10.8kb.

    пʼятницю, 26 жовтня 2012 р.

    Оголошено 'Feature Freeze' для Ruby 2.0

    Точно за розкладом, основна команда Ruby оголосила про заморожування коду нових можливостей('feature freeze') майбутнього Ruby 2.0. Це означає, що з цього моменту розробники лише будуть виправляти баги, не додаючи нових фіч в дану версію.

    Нижче я збираюся представити переклад статті "Things to Look Forward to in Ruby 2.0" у якій автор перерахував декілька нових можливостей Ruby 2.0.

    вівторок, 23 жовтня 2012 р.

    Ruby Bits.Частина 2


    Для багатьох не секрет, що Ruby — це потужна мова програмування. Але чи використовуєте ви її в повній мірі?
    У другій частині курсу від Code School ви зможете познайомитися з найбільш корисними можливостями метапрограмування у Ruby.

    У цьому курсі ви дізнаєтеся про:
    • Використання Procs і лямбда для зберігання і виконання блоків коду
    • Різні способи для передачі блоків у методи
    • Як використовувати необов'язкові блоки
    • Динамічне визначення та виклик методів
    • Відповідь на неіснуючі методи
    • Управління контекстом, в якому виконується код

    В кінці курсу, ви зможете використовувати вивчені можливості для побудови Domain Specific Languages(DSL).

    >>> Перейти до курсу

    Реліз JRuby 1.7.0


    Спільноті JRuby рада оголосити про випуск JRuby 1.7.0, починаючи з якої заявлена офіційна підтримка Ruby 1.9.x.

    Після півтора років розробки вийшов мажорний реліз відкритої багатоплатформної реалізації інтерпретатора мови програмування Ruby, написаної цілком на Java.

    В JRuby 1.7  проведений величезний обсяг робіт, десятки учасників, і покращення у кожній підсистемі. І тепер за замовчуванням JRuby працює у режимі сумісності Ruby 1.9.3. Втім, не означає, що реалізація не буде більше вдосконалюватися. Це означає лише, що в майбутньому будуть вирішуватися проблеми з якими зіткнуться користувачі. На даний момент, розробники планують випускати нові версії 1.7.x кожні 2-3 тижні.

    1.7 є першим стабільним JRuby з підтримкою нової можливості JVM - invokedynamic. Ви можете включити використання invokedynamic для Java 7, але вона по замовчуванню відключена, через проблему в JVM. На Java 8 , вона включений за умовчанням: http://wiki.jruby.org/PerformanceTuning.

    Що нового:
    • Режим сумісності з 1.9.3 тепер використовується по замовчуванню(1.8 необхідний для підтримки 1.8.7)
    • Стандартна бібліотека оновлена до 1.9.3p286
    • Багато виправлень сумісності з 1.9.x
    • Підтримка invokedynamic
    • Численні покращення продуктивності
    • Припинена підтримка Java 5(тепер обов'язкова Java 6+).
    • Вирішені всі відомі проблеми з кодуваннями у 1.9
    • Покращення і виправлення для Java інтеграції
    • Краща підтримка для Solaris, ARM Linux.
    • Оновлення до Rubygems 1.8.24
    • Оновлення до Rake 0.9.2.2

    суботу, 13 жовтня 2012 р.

    Ruby 1.9.3-p286

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

    Для Linux:
    $ rvm get head
    
    $ rvm upgrade ruby
    Are you sure you wish to upgrade from ruby-1.9.3-p194 to ruby-1.9.3-p286? (Y/n):
    

    Для Windows доступний для завантаження RubyInstaller 1.9.3-p286.

    вівторок, 9 жовтня 2012 р.

    Курс по Ruby на Codecademy

    На навчальному порталі Codecademy з'явився курс з мови програмування Ruby.

    Курс інтерактивний, інтерпретатор працює прямо в браузері. Складається з більше сотні вправ, розбитих на 5 блоків. Частина вправ кожного блоку ввідні, а частина - приклад реалізації найпростіших додатків.

    Курс можна рекомендувати, тим, хто тільки починає вивчення Ruby.

    Курс на англійській, але на простій і зрозумілій.


    середу, 15 серпня 2012 р.

    Стилізація sinatra-flash для Bootstrap

    Про гем sinatra-flash, я писав у статті Flash-повідомлення і Sinatra
    Задачею є створити замість стандартного styled_flash, методу-помінчника для Sinatra, який відображатиме попередження стилізовані під Bootstrap.


    вівторок, 14 серпня 2012 р.

    Як зробити локальий веб-сервер загальнодоступним

    Сьогодні відкрив для себе чудовий сервіс, який дозволяє швидко і просто зробити локальний веб-сервер загальнодоступним в Інтернеті.

    Зустрічайте ProxyLocal

    Це програмне забезпечення складається з клієнтської і серверної частин. Серверна частина працює на сервері proxylocal.com, і ви можете використання його ресурси абсолютно безкоштовно. Клієнт написаний на мові Ruby і поширюється як gem, його вихідний код відкритий і доступний на GitHub.

    Інсталяція

    ProxyLocal - це утиліта командного рядка.

    Відкрийте термінал і наберіть:
    $ gem install proxylocal
    

    Використання

    Припустимо, ваш локальний веб-сервер запущений на порту 9292. Щоб зробити його загальнодоступним виконайте в терміналі:
    $ proxylocal 9292
    Local server on port 9292 is now publicly available via:
    http://o18f.t.proxylocal.com/
    

    Тепер ваш локальний сервер на порту 9292 доступний через:
    http://o18f.t.proxylocal.com/
    

    Також ви можете вказати бажане ім'я, яке ви хочете використовувати, наприклад:
    $ proxylocal 9292 --host testhost
    Local server on port 9292 is now publicly available via:
    http://testhost.t.proxylocal.com/
    

    вівторок, 3 липня 2012 р.

    ВКонтакте → Авторизація додатків з Ruby і Net::HTTP

    На днях виникло бажання переписати код своєї бібліотеки для для авторизації ВКонтакте і здійснення запитів до API, використовуючи тільки стандартні модулі Ruby.

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

    Спочатку встановимо необхідні параметри.

    Детально про параметри звернення можна прочитати в документації.
    client_id - ідентифікатор вашого додатку.
    Тут слід зазначити, що ми будемо використовувати параметр display із значенням wap, так в цьому варіанті сторінки практично відсутній JavaScript.
    scope являє собою список прав, до яких ми хочемо отримати доступ.

    Звертаємося до сторінки авторизації




    Парсимо відповідь


    Подивимося на код сторінки авторизації. Найбільше нас буде цікавити наступна частина:


    Для подальшої відправки форми необхідно розпарсити всі input'и (и тому числі і приховані), а також URL, на який сабмітиться форма.


    Авторизуємось


    Підставляємо в параметри запиту електронну пошту та пароль користувача і відправляємо форму:


    Отримуємо куку




    Встановлюємо куку




    Отримуємо код


    Наступним етапом, якщо користувач цього ще не робив, треба дати додатку ті права, які ми запитували в параметрі scope. Для цього нам буде запропонована сторінка з формою.

    В результаті отримуємо відповідь наступного вигляду:
    http://oauth.vk.com/blank.html#code=xxxxxxxxxxxxxxxxxx



    Даний метод авторизації не є офіційним і може змінитися.

    вівторок, 22 травня 2012 р.

    CarrierWave з DataMapper у Sinatra

    У вільний час займаюся розробкою веб-додатку на Sinatra з використанням DataMapper. І ось задався питанням завантаження аватарів на сервер та їх після-обробкою.

    Переглянувши доступні інструменти для забезпечення цієї функціональності, вибір впав на бібліотеку CarrierWave, яка на відміну від більшості інших не зав'язана на Rails/ActiveRecord.

    CarrierWave описує себе, як "першокласне рішення для завантаження файлів для Rails, Sinatra та інших веб-додатків на основі Rack". Проект був започаткований у серпні 2008 року, і перший випуск відбувся в березні 2009 року. Перша його назва була Merb::Upload і він був без підтримки Rails.

    Той факт, що CarrierWave почав своє життя в якості плагіна для Merb може пояснити його модульність, гнучкість і розширюваність.

    Завдяки fog, він має підтримку Amazon S3, Rackspace Cloud Files і Google Storage for Developers. Він також підтримує звичайне зберігання файлів і GridFS в MongoDB.
    Має підтримку незліченної кількості ORM: ActiveRecord, Mongoid, DataMapper, Sequel, MongoMapper, CouchDB.
    Обробка зображення доступна засобами RMagick, ImageScience або MiniMagick.
    Сама по собі ця бібліотека дуже добре документована, і якщо раптом когось цікавлять деталі, то читайте wiki.

    У цій статті для прикладу ми напишемо просту фотогалерею.
    Наступні gem`и повинні бути встановлені:
    • sinatra
    • datamapper
    • dm-sqlite-adapter
    • slim
    • carrierwave - для завантаження зображень
    • carrierwave-datamapper - для зв'язку DataMapper і CarrierWave
    • rmagick - для створення мініатюр зображень(в Ubuntu потрібно встановити пакет libmagick++-dev)

    пʼятницю, 18 травня 2012 р.

    Розгортання додатку Sinatra на OpenShift

    Red Hat OpenShift - це нова, вільно-масштабована "платформа як послуга(Platform as a service, PaaS) для розробки веб-додатків. На даний момент підтримує Java, Ruby, Node, Python, PHP і Perl.

    Картриджі - це компоненти додатку OpenShift, які включають в себе бази даних(MySQL, PostgreSQL, MongoDB) та інші утиліти(Cron, phpMyAdmin, RockMongo, OpenShift Metrics). Додавання картриджа у додаток забезпечує бажану функціональність.

    Для початку необхідно зареєструватися на сайті https://openshift.redhat.com і створити новий додаток.
    Вибрати тип додатку(в нашому випадку це Ruby 1.8.7). Вказати ім'я додатку і простір імен.
    Вітання, тепер ви у хмарах!
    Новий додаток буде доступний за URL виду:
    http://<ім'я додатку>-<простір імен>.rhcloud.com

    OpenShift використовує розподілену система керування версіями коду Git. Коли ви внесете зміни у віддалений репозиторій, сервіс автоматично розгорне ваш код і перевантажить додаток якщо необхідно.

    четвер, 17 травня 2012 р.

    Ведення логів у Mechanize

    Для того, щоб проаналізувати, що пішло не так, коли Mechanize викликає виключення, виникає необхідність ведення логів. Mechanize може реєструвати практично будь-які події, включаючи заголовки запитів. Для цього потрібно передати екземпляр класу Logger у метод Mechanize#log.
    # -*- encoding: utf-8 -*-
    
    require 'mechanize'
    require 'logger'
    
    log = Logger.new($stderr)
    log.level = Logger::DEBUG
    
    agent = Mechanize.new do |a|
      a.log = log
    end
    
    agent.get('http://google.com')
    
    Отриману інформацію надалі можна використати для аналізу подій, виявлення помилок та збоїв.
    https://gist.github.com/2718143#file_mechanize1.log
    Офіційна документація по класу Logger

    Також існує менш відомий, але не менш корисний спосіб ведення логів за допомогою методу Mechanize#agent.http.debug_output:
    # -*- encoding: utf-8 -*-
    
    require 'mechanize'
    
    agent = Mechanize.new do |a|
      a.agent.http.debug_output = $stderr
    end
    
    agent.get('http://google.com')
    
    https://gist.github.com/2718143#file_mechanize2.log

    Оновлюємо статус ВКонтакте за допомогою Ruby

    Сьогодні вечором виникло бажання, щоб на моїй сторінці ВКонтакте відображався таймер зворотнього відліку до початку Євро-2012 прямо в статусі. Написати простенький скрипт на Ruby для такого достатньо просто.
    З інструментів я використовував свою бібліотеку для роботи з API ВКонтакте. Якщо комусь цікаво, як вона працює, можете почитати статтю ВКонтакте → Авторизація Standalone-додатків використовуючи OAuth 2.0 на прикладі Ruby і Mechanize.

    Не вдаючись в подробиці, ось посилання на приклад скрипта.

    Здавалось би залишилось додати скрипт у cron і насолоджуватись результатом.
    Наступний рядок у /etc/crontab не приніс бажаних результатів.
    */1 * * * * user ruby /home/user/days_to_euro.rb
    
    Скрипт всього-на-всього не виконувався.
    Причиною проблеми виявився Ruby Version Manager(RVM). Змінюємо на наступний рядок.
    */1 * * * * user bash -c 'source /home/user/.rvm/scripts/rvm && /usr/bin/env ruby /home/user/days_to_euro.rb'
    

    І вуаля: тепер скрипт успішно виконується і так же успішно завершує роботу з помилкою:
    `default_gemfile': Could not locate Gemfile (Bundler::GemfileNotFound)
    
    Це відбувається тому, Bundler шукає Gemfile в каталозі в якому виконується, а Gemfile там звісно ж немає.
    Потрібно вказати де шукати Gemfile.
    ENV['BUNDLE_GEMFILE'] = File.join(File.dirname(__FILE__) ,'Gemfile')
    
    Вищевказаний рядок потрібно додати у шапку скрипта.

    Тепер все добре і скрипт працює.

    P.S. До Євро-2012 залишилось 21 день 23 години 43 хвилини

    неділю, 13 травня 2012 р.

    QtRuby: позиціювання віджетів

    У цій статті, ми познайомимося з основами розміщенням віджетів у вікні додатку QtRuby.

    Коли ми розробляємо графічний інтерфейс додатку, ми вирішуємо, які компоненти ми будемо використовувати і як ми будемо організовувати ці компоненти. Щоб організувати компоненти, ми використовуємо спеціальні невидимі ​​об'єкти, так звані менеджери компонування(layout managers).
    Qt надає кілька варіантів. Ми можемо використовувати абсолютне позиціювання, вбудовані менеджери компонування або створити власний менеджер компонування. Також ми також можемо візуально будувати макети допомогою Qt Designer.

    суботу, 12 травня 2012 р.

    Введення в QtRuby

    Ця стаття є введенням в програмування графічного інтерфейсу користувача(GUI) з використанням бібліотеки Qt, мови Ruby, і qt4-qtruby.

    Якщо ви раніше ніколи не користувалися Qt, рекомендую почитати документ Як вивчати Qt. Не забувайте, що, як і більшість статей про Qt, ця сильно орієнтована на C++.

    Найкращий спосіб почати програмувати з QtRuby це ознайомитися з прикладами коду, які знаходяться в директорії qtruby/examples.

    Для початку розімнемо пальці. А саме напишемо Hello World. Куди ж ми без нього? Він містить тільки необхідний мінімум, що отримати робочий Qt додаток.
    # -*- encoding: utf-8 -*-
    
    require 'Qt'
    
    app = Qt::Application.new(ARGV)
    hello = Qt::PushButton.new("Hello World!")
    hello.resize(100, 30)
    hello.show
    app.exec
    

    пʼятницю, 11 травня 2012 р.

    Інсталяція QtRuby з Ruby 1.9.3 на Ubuntu 12.04

    • Ubuntu 12.04 LTS
    • Остання версія Ruby 1.9.3p194 зібрана з RVM
    • Qt 4.8.1 з репозиторію
    • Остання стабільна версія QtRuby 2.2.0
    sudo apt-get install cmake libqt4-dev libqwt5-qt4-dev libqscintilla2-dev libsmokeqt4-dev
    wget http://rubyforge.org/frs/download.php/75633/qt4-qtruby-2.2.0.tar.gz
    tar xzvf qt4-qtruby-2.2.0.tar.gz
    cd qt4-qtruby-2.2.0/
    cmake .
    make
    sudo make install
    sudo ldconfig /usr/local/lib/
    

    неділю, 29 квітня 2012 р.

    Стрімінг в Sinatra

    Починаючи з 1.3.0, Sinatra підтримує стрімінг(streaming API). В інтернеті ви точно стикалися з його реалізацією. Наприклад стрічка Twitter чи новини ВКонтакте.

    Іноді потрібно почати відправляти дані клієнту прямо в процесі генерування частин цих даних. В особливих випадках потрібно постійно відправляти дані до тих пір, поки клієнт не закриє з'єднання. Ви можете використовувати метод stream замість написання власних "обгорток".

    Почнемо з класичного прикладу з документації Sinatra:
    get '/' do
      stream do |out|
        out << "It's gonna be legen -\n"
        sleep 0.5
        out << " (wait for it) \n"
        sleep 1
        out << "- dary!\n"
      end
    end
    

    Якщо сервер не підтримує стрімінг (наприклад, WEBRick), то всі дані будуть відправлені за один раз відразу після того, як блок, переданий в stream, завершиться.

    понеділок, 23 квітня 2012 р.

    mpd_client - ще одна бібліотека MPD для Ruby

    Велосипеди я люблю. Кататися люблю. Винаходити не люблю.

    Хочу представити вашій увазі ще одну клієнтську бібліотеку для Music Player Daemon, повністю написану на Ruby. Зустрічайте mpd_client, порт бібліотеки python-mpd.

    Інсталяція

    Як і будь-який інший gem - виконайте в консолі:
    $ gem install mpd_client
    

    Використання

    Вся функціональність міститься у класі MPDClient.
    Для початку роботи з демоном MPD необхідно створити екземпляр цього класу:
    client = MPDClient.new
    

    Далі необхідно створити з'єднання з сервером, вказавши назву хосту і порт. Наприклад, запущений на цій самій машині:
    client.connect('localhost', 6600)
    

    Після успішного з'єднання з сервером можна здійснювати запити до MPD:
    puts client.mpd_version             # надрукувати версію mpd
    puts client.search('title', 'ruby') # вивести результат виконання команди 'search title ruby'
    client.close                        # відправити команду close
    client.disconect                    # від'єднатися від сервера
    

    Тут приводяться всі команди для роботи з MPD, з описом параметрів і прикладами відповідей.

    Також підтримуються списки команд використовуючи command_list_ok_begin і command_list_end:
    client.command_list_ok_begin # почати список команд
    client.update                # вставити команду update в список
    client.status                # вставити команду status в список
    client.command_list_end      # масив містить результати виконання всіх команд у списку
    

    четвер, 29 березня 2012 р.

    FSF оголосив лауреатів премії Free Software Awards 2011

    Річард Столмен (Richard Stallman) офіційно оголосив на конференції LibrePlanet 2012 лауреатів щорічної премії "Free Software Awards 2011", заснованої Фондом вільного ПЗ (FSF). Ця премія присуджується людям, які зробили найбільш значний внесок у розвиток вільного ПЗ, а також соціально значущим вільним проектам.

    У першій номінації, що вручається за просування і розвиток вільного ПЗ, премія присуджена Юкіхіро Мацумото (Yukihiro Matsumoto), автору мови програмування Ruby. Matz вже протягом 20 років бере участь у розвитку проектів GNU, Ruby та інших відкритих проектів. У своїй своїй промові Юкіхіро розповів про свій перший досвіді роботи з вільним ПЗ і підкреслив вплив GNU Emacs на Ruby.

    Цікаво, що переможцями цієї премії вже ставали у 1998 автор мови Perl Ларрі Уолл (Larry Wall) та у 2001 автор мови Python Ґвідо ван Россум (Guido van Rossum).

    >> Докладніше

    неділю, 25 березня 2012 р.

    Ruby 2.0 Enumerator::Lazy

    Продовжимо знайомитися із нововведеннями, які увійдуть у випуск Ruby 2.0.

    Нещодавно патч Enumerator::Lazy був прийнятий в ruby trunk. А це значить що в Ruby 2.0 ми зможемо:
    a = [1,2,3,4,2,5].lazy.map { |x| x * 10 }.select { |x| x > 30 } #=> обчислення не відбувається
    a.to_a #=> [40, 50], об'єкт обчислюється за один прохід
    

    Зараз Enumerator::Lazy має в своєму арсеналі select, map, reject, grep, flat_map, zip, take, take_while, drop, drop_while, cycle. Розробка активно продовжується. Якщо хочете використовувати його прямо зараз - досить скомпілювати Ruby з trunk і насолоджуватися.

    Докладніше про Enumerator::Lazy: англійською і російською.

    суботу, 24 березня 2012 р.

    Стилістика написання коду Ruby

    Пару днів назад на GitHub створили спеціальний розділ, присвячений стилям написання коду. Доступні рекомендації для наступних мов:

    Для Ruby багато що було взято з https://github.com/bbatsov/ruby-style-guide.

    вівторок, 21 лютого 2012 р.

    OmniAuth Identity з DataMapper в Sinatra

    З виходом OmniAuth версії 1.0 з'явилася нова стратегія Identity, яка дозволяє використовувати традиційну аутентифікацію по логіну і паролю.

    Раніше я вже писав про OmniAuth - раз і два.

    У цій статті ми познайомимося з стратегією під назвою Identity, яка дозволяє користувачу створити обліковий запис, вказавши ім'я користувача та пароль, замість входу через зовнішнього постачальника.

    Вихідний код цієї статті заснований на OmniAuth для Sinatra, і якщо ви не знайомі з OmniAuth цю статтю варто прочитати в першу чергу.

    вівторок, 14 лютого 2012 р.

    Sinatra: Up and Running.pdf

    Sinatra: Up and Running

    Ruby for the Web, Simply

    By Alan Harris, Konstantin Haase

    Publisher: O'Reilly Media
    Released: November 2011
    Pages: 120


    Скачати безкоштовно без реєстрації та смс даром на халяву
    Get this torrent ( Torrent File)

    понеділок, 13 лютого 2012 р.

    Налаштування will_paginate для Bootstrap у Sinatra

    Нещодавно вийшла друга версія популярного HTML-фреймворка Bootstrap. Для тих хто не в курсі що це, настійно рекомендую ознайомитися. Цей набір дозволяє створювати шаблони сайтів за лічені години(перевірено на власному досвіді) на основі готових наборів стилів, які різко спрощують розстановку елементів на сторінці та забезпечують якісну типографію.

    Крім того вийшла версія will_paginate 3.0.3, у яку крім усього іншого також ввійшов коміт, що виправляв кілька багів пов'язаних з DataMapper.
    І у зв'язку з цієї радісною новиною, я вирішив прикрутити пагінацію до свого проекту на Sinatra, у якому, як ви вже мабуть здогадалися використовується Bootstrap.

    Підключаємо необхідні бібліотеки:
    require 'will_paginate'
    require 'will_paginate/data_mapper'
    

    Вказуємо will_paginate генерувати теги у стилі Bootstrap:
    class BootstrapLinkRenderer < ::WillPaginate::Sinatra::LinkRenderer
      protected
      
      def html_container(html)
        tag :div, tag(:ul, html), container_attributes
      end
    
      def page_number(page)
        tag :li, link(page, page, :rel => rel_value(page)), :class => ('active' if page == current_page)
      end
    
      def gap
        tag :li, link(super, '#'), :class => 'disabled'
      end
    
      def previous_or_next_page(page, text, classname)
        tag :li, link(text, page || '#'), :class => [classname[0..3], classname, ('disabled' unless page)].join(' ')
      end
    end
    

    І на останок пишемо помічник, який дозволить виводити навігацію у простій формі:
    == page_navigation_links @events
    

    helpers do
    
      def page_navigation_links(pages)
        will_paginate(pages, :class => 'pagination', :inner_window => 2, :outer_window => 0, :renderer => BootstrapLinkRenderer, :previous_label => '&larr;', :next_label => '&rarr;')
      end
    
    end
    

    середу, 11 січня 2012 р.

    Проблема з авторизацією ВКонтакте через OAuth2

    Сьогодні стикнувся з помилкою при авторизації по OAuth ВКонтакте:
    {"error":"invalid_request","error_description":"redirect_uri is incorrect"}
    
    Виявляється, треба просто вказати правильний домен. Раніше якимось чином все працювало з невірним доменом.


    вівторок, 10 січня 2012 р.

    Іменовані аргументи функції в Ruby 2.0

    В Ruby 1.9 іменовані аргументи представляють із себе просто останній аргумент з хешем, як значенням по замовчуванню, і розширення граматики, за допомогою якого ініціалізується цей хеш. Мало хто знає, що в 1.9 можна зробити метод, наприклад:
    def a(opts = {}); end
    
    і викликати його як
    a(go: true, what: "string")
    

    В trunk Ruby 2.0 додали іменовані аргументи(keyword arguments) - простий спосіб вказати такий запис при визначенні методу. Наприклад:
    def step (by: step, to: limit)
      ...
    end
    
    1.step (by: 2, to: 20) do |i|
      p i
    end