четвер, 31 грудня 2009 р.

RubyUA → Підсумки року


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

До Нового Року залишились лічені години, тому хочеться згадати що було в житті блогу. Подій насправді було не дуже багато. Але все ж цей рік був не такий, як інші.
Протягом 2009 року блог пережив 4382 відвідувань(з яких 3046 абсолютно унікальних). В цілому було переглянуло 9308 сторінок.

вівторок, 29 грудня 2009 р.

Вийшов новий випуск Rails Magazine

У п'ятому випуску зокрема розповідають про Sinatra, використання Twitter API в Ruby і багато іншого.

Як завжди, ви можете завантажити безкоштовну електронну версію Rails Magazine #5

субота, 19 грудня 2009 р.

Ruby Documentation extension for Google Chrome

Я протягом довгого часу хочу перейти на Chrome. Єдине, що мене стримує – Opera. Сила звички то страшна річ. Але все ж таки час від часу дивлюся в сторону Chrome. Сьогодні після чергового оновлення, він зустрів мене повідомленням: "Новинка! У Google Chrome відтепер є розширення та синхронізація закладок."

Знайшов розширення Ruby Documentation, яке буде корисним для тих хто програмує на Ruby і користується переглядачем Google Chrome. Дозволяє здійснювати пошук по документації Ruby 1.9. Дане розширення має автодоповнення для зручності використання.
Просто і ефективно!

субота, 28 листопада 2009 р.

RESTful Sinatra

Попередні статті:
  1. Привіт, Sinatra!
  2. Привіт, DataMapper!
  3. Співаємо з Sinatra!

Прийшов час поговорити про REST архітектуру додатку та її реалізацію на Sinatra.
Особисто мені коштувало багато зусиль зрозуміти, що таке REST. Тому прошу не чіплятися до того, наскільки я спрощую термінологію, щоб сфокусуватися на самій темі.
REST - це Representational State Transfer, так звана "передача стану представлення". Фактично - це спосіб організації доступу до ресурсів. Відповідно до цієї архітектури використовується чотири типи HTTP запитів - GET, POST, PUT і DELETE.
  • GET - отримати ресурс тільки для читання
  • POST - створити новий ресурс
  • PUT - оновити існуючий ресурс
  • DELETE - видалити ресурс

Нічого не нагадує? Якщо порівняти з SQL-синтаксисом, GET - це запит SELECT, POST - це INSERT, PUT - UPDATE, і DELETE - знову просто DELETE.
Ресурси - це ті дані, з якими ми працюємо. Наприклад у нашому блозі стаття - це ресурс, коментарій - це теж ресурс. Ресурси можуть мати взаємозв'язки, та містити в собі інші ресурси. Для більшості ресурсів в нашому додатку будуть необхідні операції їх створення, отримання, оновлення та видалення.

Крім звичних GET і POST Sinatra розуміє методи PUT і DELETE. Нажаль ці методи не підтримуються броузерами, але Sinatra вміє з ними працювати через прихований елемент форми з ім'ям "_method" і значенням, рівним методу HTTP: put або delete. Наприклад:
<form method="post" action "/destroy">
  <input type="hidden" name="_method" value="delete">
  <button type="submit">Destroy it</button>
</form>

Далі ми будемо вважати клас-контролер реалізацією інтерфейсу REST.
Наш контролер буде реалізовувати наступні сім дій(методів).
Чотири цих:
  • show: обробляє GET запит для відображення індивідуального ресурсу, який ідентифікується виразом params[:id]
  • create: обробляє POST запит для створення нового екземпляру ресурсу
  • update: обробляє PUT запит для оновлення існуючого ресурсу, ідентифікованого виразом params[:id], використовуючи дані зв'язані з запитом
  • destroy: обробляє DELETE запит для видалення екземпляра ресурсу, ідентифікованого виразом params[:id]

І три цих:
  • index: обробляє GET запит для відображення колекції ресурсів
  • new: обробляє GET запит, який створює логічну структуру нового ресурсу і передає її клієнту. Цей ресурс не буде збережений на сервері. Можна вважати, що дія new створює порожню форму, яка передається клієнту для заповнення.
  • edit: обробляє GET запит, який повертає вміст ресурсу, ідентифікованого виразом params[:id], в форму, пристосовану для редагування цього вмісту

Не важко помітити, що ці сім дій включають чотири базових операції для створення, читання, оновлення і видалення ресурсу - CRUD (create, read, update, delete). Серед них також є дії для виводу переліку ресурсів та дві додаткові дії, які повертають клієнту новий та існуючий ресурси в форму, призначену для редагування.

Для Sinatra назви цих дій не мають ніякого значення, і використовуються мною тільки для зручності, і є запозиченими з Rails.
Для того щоб реалізувати REST підхід у нашому додатку треба поступити інакше ніж у попередній статті. В першу чергу один і той же URL може в залежності залежати від типу HTTP запиту відповідати різним методам. Наприклад URL
/posts/1
повинен викликати метод show(для відображення статті №1), якщо був використаний запит GET, але у випадку запиту DELETE повинен викликати метод destroy.


Все що нам залишилося зробити, це реалізувати цих сім методів у нашому контролері і оновити шаблони представлень.

понеділок, 23 листопада 2009 р.

Співаємо з Sinatra!


Ця стаття є так би мовити третьою. У двох попередніх ми вже встигли познайомитися з веб-фреймворком Sinatra (Привіт Sinatra!) та ORM бібліотекою DataMapper (Привіт DataMapper!). Прийшов час застосувати ці знання на практиці. Напишемо наш "proof of concept" додаток, використовуючи Sinatra, DataMapper, HAML, SASS. Я вирішив, що ми проведемо наші навчальні заняття за написанням блогу.

Sinatra не піклується про те, як ви організовуєте ваш додаток. На відміну від Rails, Sinatra не накладає ряд серйозних обмежень на структуру ваших додатків. Ви можете покласти все в один файл, або розбити на структуру каталогів. Звичайно, якщо ви розіб'єте на окремі файли, потрібно підключати їх в міру необхідності - у Sinatra немає узгоджень, як в Rails, про те де шукати ці файли.
Моя структура каталогів, вона дуже проста:
/
  blog.rb
  db/
    db.sqlite3
  views/
    layout.haml
    /posts
      edit.haml
      index.haml
      new.haml
      show.haml

Я поклав все крім шаблонів в один файл. Таким чином конфігурації, моделі і всі події будуть у файлі blog.rb. Також Sinatra по замовчуванню підхоплює каталог views, який містить шаблони представлень.

четвер, 12 листопада 2009 р.

Codepad - онлайн компілятор/інтерпретатор коду

Бороздячи безкрайні простори інтернету, натрапив на дуже цікавий і корисний сервіс, який вміє компілювати/інтерпретувати код онлайн.
Codepad - це pastebin-сервіс, який виконує код. Ви просто вставляєте код, а Сodepad виконує його і повертає короткий URL, яким ви можете обмінюватися з іншими. Ви можете вставити цей URL на форумі або переслати по електронній пошті, щоб отримати допомогу або ж, навпаки, щоб показати комусь як щось зробити. Або врешті-решт використовувати його, коли у вас під рукою немає потрібного інтерпретатора.
Підтримує: C, C++, D, Haskell, Lua, OCaml, PHP, Perl, Plain Text, Python, Ruby, Scheme, Tcl.



Мій маленький приклад: http://codepad.org/YRUOEFKR

понеділок, 9 листопада 2009 р.

Привіт, DataMapper!

DataMapper - це ORM бібліотека (англ. Object-relational mapping, Обє'ктно-реляційна проекція - технологія, яка зв'язую бази даних з концепцією об'єктно-орієнтовного програмування, створюючи "віртуальну об'єктну базу даних"). DataMapper написана на Ruby, і широко використовується у таких фреймворках як Merb та Sinatra. Вона була розроблена, щоб усунути недоліки бібліотеки ActiveRecord, яка використовується в Ruby on Rails по замовчуванню. DataMapper слідує стандартам ORM-моделі: таблиці відображаються у вигляді класів, записи - у вигляді об'єктів, а стовпці - у вигляді властивостей цих об'єктів. Методи класу використовуються для здійснення операцій на рівні таблиці, а методи екземпляра здійснюють операції над окремими рядками.
Якщо в базі даних є таблиця з назвою posts (записи), то наш застосунок матиме клас Post. Рядки цієї таблиці відповідають об'єктам класу - конкретний запис представляється як об'єкт класу Post. У межах цього об'єкту для отримання доступу до окремих стовпців і встановлення їм значення, використовуються властивості.

Інсталяція DataMapper

DataMapper доступний через менеджер пакетів Ruby Gem:
gem install dm-core

Якщо ви плануєте використовувати DataMapper з базою даних, встановіть адаптер бази даних з проекту DataObjects. В залежності від ваших уподобань, це може бути do_mysql, do_postgres або do_sqlite3.
gem install do_sqlite3

середа, 28 жовтня 2009 р.

Привіт, Sinatra!

Sinatra — об'єктно-орієнтований програмний каркас(framework) для створення веб-застосунків, написана на мові програмування Ruby. На офійному сайті написано, що Sinatra це навіть не фреймворк, а DSL для створення веб-додатків. Залежить від інтерфейсу веб-сервера Rack. Вона є альтернативою іншим Ruby фреймворкам, таким як Ruby on Rails, Merb, Nitro та Camping.
Sinatra є відкритим програмним забезпеченням і розповсюджується під ліцензією MIT.
Розроблена та створена Blake Mizerany, Sinatra є крихітною(близько 1500 рядків коду, що майже 1/100-а розміру Rails) та надзвичайно гнучкою. Вона не слідує типовій архітектурі Модель-Вид-Контролер(Model-View-Controller, MVC), яка використовується в інших фреймвоках, таких як Ruby On Rails. Натомість, Sinatra зосереджена на "швидкому створенню веб-додатків на Ruby із мінімальними зусиллями". Sinatra використовує всі можливості Ruby і є його оригінальним розширенням.

Sinatra дає незвичайне відчуття присутності. Це як музика. Ви диригент оркестру. І перша скрипка звучить так, як ви їх наказали, хоча ви не обов'язково повинні знати, як на ній грати. Але в той же час у вас є можливість посмикати струни, побити в барабани, засурмити фанфари. Sinatra крихітна, гнучка і модульна. Ви вільні у виборі, що використовувати у якості бібліотеки моделі, двигуна шаблонів, двигуна JavaScript. Незважаючи на свій юний вік Sinatra є потужним і багатообіцяючим інструментом, про що свідчить підтримка з боку таких таких маститих проектів, як Engine Yard, Heroku, GitHub і Songbird.

Інсталяція Sinatra
Розпочнемо знайомство із встановлення Sinatra.
У вас уже повинен бути встановлений Ruby. Для тих хто вже користується новою гілкою 1.9 можу вас втішити - починаючи з версії 0.9.2, Sinatra повністю сумісна з Ruby 1.9 і Rack 1.0. Найпростіший шлях - встановити Sinatra через Rubygems:
$ gem install sinatra


Привіт, Sinatra
Тепер давайте створимо наш перший веб-додаток.
# myapp.rb
require 'rubygems'
require 'sinatra'

get '/' do
"Привіт, Sinatra!"
end


четвер, 22 жовтня 2009 р.

Try Ruby! Now With 1.9

Веб-версія IRB(interactive ruby prompt) та 15 хвилинний навчальний посібник для людей, які хочуть познайомитися з Ruby. Тепер версія 1.9.


середа, 14 жовтня 2009 р.

vk.com. Частина 7

У цьому дописі мова знову піде про ВКонтакте і WWW::Mechanize. Хоч він і йде під номером сім, він не є продовженням попередніх частинами, хоча для повного розуміння про далі буде йти мова, бажано ознайомитися з ними. З них ви можете дізнатися, як робити наступні речі ВКонтакте:

  • Отримання новин профілю (кількості нових повідомлень, фотографій, відео, друзів, груп).

  • Отримання списку друзів

  • Отримання приватних повідомлень

  • Написання приватних повідомлень



Я вже писав про те, що домен VK.COM перейшов під контроль соціальної мережі ВКонтакте. Майже з тих самих пір авторизація користувачів на сайті vkontakte.ru відбувається через редірект login.vk.com. Це викликає незручність при авторизації за допомогою WWW::Mechanize.

require 'mechanize'
require 'json'

class Vkontakte
def initialize
@ua = WWW::Mechanize.new{|agent|
agent.user_agent_alias = 'Linux Mozilla'
agent.follow_meta_refresh = true
}
end

# Authorisation by submitting email and password (Login)
#
def login_force(uid, email, pass)
url = "http://login.vk.com/?act=login"
page = @ua.post(url, {'email' => email, 'pass' => pass, 'expire' => '1', 'vk' => 1})
s = page.body.match(/'s' value='(.+?)'/)[1]
@ua.post('http://vkontakte.ru/login.php?op=slogin&redirect=1', {'s' => s})
user_page = @ua.get('http://vkontakte.ru/profile.php')
end

end

if __FILE__ == $0
id = "xxxxxxxx"
email = "user@example.com"
pass = "your_password"

vkontakte_agent = Vkontakte.new
vkontakte_agent.login_force(id, email, pass)

end


Далі можна продовжувати роботу з ВКонтакте як звичайно.

вівторок, 29 вересня 2009 р.

Proxy list fetcher using Ruby & Nokogiri

А чому б нам не зробити накручувалку, яка голосує за що-небудь ? "Чорні"(брудні) технології залишимо нашим політиком. А самі займемося чимось корисним.

Цей скрипт складає список проксі-серверів з сайту proxy4free.com, і записує його до файлу proxy_list.txt.

# -*- encoding: utf-8 -*-

require 'nokogiri'
require 'open-uri'

file = File.new('proxy_list.txt', 'w')
url = 'http://www.proxy4free.com/page1.html'
# Get a Nokogiri::HTML:Document for the page
doc = Nokogiri::HTML(open(url))

# Search for nodes by css
doc.css('table tr.text').each do |tr|
ip = (tr/"td:nth(1)").first.inner_html
if ip.match(/^(\d{1,3}\.){3}\d{1,3}$/)
port = (tr/"td:nth(2)").first.inner_html
file.puts "#{ip}:#{port}"
end
end
file.close



Керівництва до дії:

  1. Do something

  2. Do something else

  3. Do something once more

  4. <Do something so much you need>

  5. ?????

  6. PROFIT!


вівторок, 22 вересня 2009 р.

RubyInstaller for Windows



RubyInstaller (раніше відомий як One-Click Installer) - це автономний Windows-інсталятор, який включає в себе саму мову Ruby, середовище виконання, важливу документацію (містить документацію Ruby Core і стандартних бібліотеках, а також книжку "The Book of Ruby" написану Huw Collingbourne), та багато іншого.
Для інсталяції Ruby в один клік необхідно спочатку завантажити версію, яку ви хочете (на даний момент доступні 1.8.6 та 1.9.1) і запустити .exe файл.
Після цього в меню "Пуск" з'явиться відповідний пункт:


Хочу замітити цей проект знаходиться на першому місці по кількості скачувань з сайту RubyForge. На даний момент це - 3,572,852 раз.

неділя, 13 вересня 2009 р.

З Днем програміста!

irb(main):001:0> require 'date'
=> true
irb(main):002:0> (Date.new(2009) + 255).to_s
=> "2009-09-13"


День програмі́ста — офіційне професійне свято програмістів, яке відзначають у 256-й день року (255-й з нуля). У високосний рік це 12 вересня, а у невисокосний — 13 вересня.
Таку нетрадиційну дату було вибрано через те, що число 256 відповідає кількості чисел, яку можна виразити за допомогою вісімкового байта, це — від 0 до 255 (двійкова система: 11111111), які можна представити за допомогою одного байта, який складається з 8 бітів, котрі в свою чергу можуть мати значення 0 або 1, тобто — 28 випадків. Також 256 у шістнадцятковій системі числення це 100 (0x100). А також це максимальна степінь числа 2, яка менша 356 (днів у році).

Вітаю всіх, хто має відношення!

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

Keyword: login.vk.com/?act=login



Судячи з активності, або народ переживає, або щось не так...
Доменне ім’я vk.com віднедавна належить мережі "В контакте". VK на пути к мировому господству. А API нормальне не можуть надати, так то.

понеділок, 7 вересня 2009 р.

wxRuby → Сайзери (2 частина)

У попередній статті ми познайомилися з позиціонуванням віджетів. А тепер перейдемо до найцікавішого, до огляду сайзерів, які є у бібліотеці wxRuby. І на прикладах побачимо, як впливають на розміщення елементів прапорці з методу Wx::Sizer#add().
У якості прикладу розглянемо код, на основі якого ми будемо експериментувати з сайзерами надалі.
# -*- encoding: utf-8 -*-

require 'wx'

class MainWindow < Wx::Frame
def initialize
super(nil, :id => -1, :title => 'Розмір має значення')
self.size = [300, 200]
self.do_sizer
show
end

def do_sizer
sizer = Wx::BoxSizer.new(Wx::VERTICAL)
set_sizer(sizer)
end
end

class SimpleApp < Wx::App
def on_init
MainWindow.new
end
end

app = SimpleApp.new
app.main_loop()


У цьому прикладі оголошується клас вікна MainWindow, у конструкторі якого викликається метод do_sizer(). Всередині цього методу у майбутніх прикладах відбуватиметься все найцікавіше, в тому сенсі, що у ньому ми і будемо розміщувати елементи керування. Інший код змінюватись не буде, тому в усіх наступних прикладах буде наводитись тільки цей метод.

субота, 5 вересня 2009 р.

wxRuby → Сайзери (1 частина)

Під час створення графічного інтерфейсу, вам потрібно займатися розміщенням елементів на формі. Наприклад, вам може знадобитись текстове поле і кнопка справа під ним. Ви можете розмістити ці елементи керування(Wx::TextCrt і Wx::Button), чітко вказавши позицію і розміри у пікселях. Ймовірно це не найкраща ідея, але ви можете зробити це у будь-якому випадку:
# -*- encoding: utf-8 -*-

require 'wx'

class HelloFrame < Wx::Frame
def initialize
super(nil, :id => -1, :title => 'Hello World!', :size => [200, 200])
text = Wx::TextCtrl.new(self, :id => -1,
:text => 'Type in here',
:pos => [0, 0],
:size => [200, 175],
:style => Wx::TE_MULTILINE)
button = Wx::Button.new(self, :id => -1,
:label => 'Press me',
:pos => [100, 175],
:size => [100, 25])

show
end

end

class HelloApp < Wx::App
def on_init
HelloFrame.new
end
end

app = HelloApp.new
app.main_loop()


Результат виконання скрипта:



Чому це погана ідея? Спробуйте збільшити і зменшити розміри вікна. Елементи залишаються на своїх місцях.



wxWidgets використовує інший підхід до розміщення елементів на формі. Елементи розміщуються не лише по відношенню до верхнього лівого кута. Їхній розмір також задається по відношенню до висоти і ширини.
Тобто, повертаючись до прикладу із статті Welcome to wxRuby!, ми помістили у вікно лише одну кнопку, по замовчуванню вона має висоту і ширину рівну, відповідно, висоті і ширині вікна.

Замість організації віджетів, використовуючи точні розміри і позиції, можна використовувати так звані сайзери, тобто класи похідні від Wx::Sizer. Саме сайзери визначають поведінку дочірніх елементів при зміні розмірів головного вікна. На мою думку, сайзери є найбільш складною для освоєння частиною бібліотеки wxRuby. І саме сайзерам буде присвячена ця стаття.

четвер, 3 вересня 2009 р.

wxRuby → Вікно

У статті Welcome to wxRuby! ми познайомилися з бібліотекою віджетів wxWidgets та обгорткою для роботи з Ruby. Також ми створили простий додаток на wxRuby, який показує вікно з однією кнопкою.

Розглянемо докладніше цей код.
У класі HelloApp є метод on_init(), який викликається під час запуску додатку.
Займемося головним вікном. За створення вікна відповідає конструктор класу Wx::Frame. Фрейм - це вікно, розмір і позиція якого можуть бути змінені користувачем. Зазвичай воно має рамку і заголовок, а також опціонально може містити рядок меню, панель інструментів і рядок стану(про які ми поговоримо в одній із майбутніх статей).

Конструктор класу Wx::Frame приймає 7 параметрів:
:parent => (Wx::Window) - це посилання на батьківський об'єкт(обов'язковий параметр)
:id => (Fixnum) - ідентифікатор вікна. -1 - значення по замовчуванню
:title => (String) - заголовок вікна
:pos => (Wxruby2::Point) - позиція вікна на екрані
:size => (Wxruby2::Size) - розмір вікна
:style => (Fixnum) - стиль вікна
:name => (String) - назва вікна

Змінимо код додатку з першої частини так, щоб наше вікно з'явилося у верхньому лівому куті і мало розмір 320х240 пікселів. Зміни вносимо у метод initialize() класу HelloFrame:

super(nil, :id => -1, :title => 'Hello World!', :pos => [0, 0], :size => [320, 240], :style => Wx::DEFAULT_FRAME_STYLE, :name => 'frame')


Щоб вікно з'явилося у центрі екрану можна скористатися методом centre():
self.centre


Для зміни позиції вікна після ініціалізації можна скористатись методам move(Wx::Point point):
self.move([100, 100])


Для зміни розміру вікна є метод set_size(Wx::Size size):
self.set_size([640, 480])


Для вікна можна задати один із стилів:
Wx::DEFAULT_FRAME_SLYLE - стиль по замовчуванню. Включає в себе Wx::MINIMIZE_BOX|Wx::MAXIMIZE_BOX|Wx::RESIZE_BORDER|Wx::SYSTEM_MENU|Wx::CAPTION|Wx::CLOSE_BOX|Wx::CLIP_CHILDREN
Wx::ICONIZE - показувати мінімізоване вікно. Тільки Windows
Wx::CAPTION - показувати заголовок вікна
Wx::MINIMIZE - аналогічно Wx::ICONIZE
Wx::MINIMIZE_BOX - показувати кнопку згортання вікна
Wx::MAXIMIZE - показувати максимізоване вікно. Тільки Windows
Wx::MAXIMIZE_BOX - показувати кнопку розгортання вікна на весь екран
Wx::CLOSE_BOX - показувати кнопку закриття вікна
Wx::STAY_ON_TOP - показувати поверх всіх вікон
Wx::SYSTEM_MENU - вікно буде мати системне меню
Wx::RESIZE_BORDER - показувати рамку для зміни розміру вікна.
Wx::FRAME_TOOL_WINDOW - вікно з рамкою невеликого розміру, і також вікно не буде показуватися на панелі задач. Тільки Windows і GTK+
Wx::FRAME_NO_TASKBAR - нормальне вікно, але воно не буде показуватися на панелі задач. Тільки Windows і GTK+
Wx::FRAME_FLOAT_ON_PARENT - вікно буде показуватися тільки поверх батьківського вікна (на відміну від Wx::STAY_ON_TOP)

Для того щоб створити вікно, розмір якого не може змінювати користувач, можна використати таку комбінацію стилів:
Wx::DEFAULT_FRAME_STYLE & ~ (Wx::RESIZE_BORDER|Wx::RESIZE_BOX|Wx::MAXIMIZE_BOX)

Тепер ви можете поекспериментувати із розміром, позицією і стилями вікна.
Стаття вийшла доволі коротка, і ми тут не розглянули всі нюанси роботи з вікнами. Виправлю цей недолік у майбутніх статтях.
На домашнє завдання така задачка: у випадку натиснення на кнопку пересунути вікно у позицію [10, 10].

На все добре і успіхів.

вівторок, 1 вересня 2009 р.

wxRuby → Welcome to wxRuby!

Цим записом я розпочну серію статей присвячену основам створення графічних додатків за допомогою бібліотеки wxWidgets на мові Ruby.

wxWidgets(раніше відома як wxWindows) — це крос-платформена бібліотека інструментів з відкритим вихідним кодом для побудови графічного інтерфейсу користувача(GUI).
wxWidgets розповсюджується під ліцензією LGPL. Проект був запущений в 1992 Юіаном Смартом (Julian Smart), який до сих пір залишається головним розробником. У 2004 році проект wxWidgets на прохання Microsoft Corporation змінив оригінальну назву "wxWindows" на "wxWidgets", за що отримав фінансову допомогу.
wxWidgets дозволяє створювати додатки для багатьох комп'ютерних платформ із мінімальними змінами у вихідному коді, або взагалі без них. Вона підтримує системи Microsoft Windows, Apple Macintosh, UNIX-подібні(для X11, Motif і GTK+), OpenVMS і OS/2. WxWidgets не імітує вигляд компонентів, використовуючи графічні примітиви різних підтримуваних платформ. Натомість wxWidgets надає тонку абстракцію до існуючих компонентів системи.
Бібліотека розроблена на C++, але може бути підключеною до багатьох інших розповсюджених мов, таких як Ruby, Python, Perl, Java, C#/.NET та інших.


wxRuby - це обгортка бібліотеки wxWidgets для роботи з Ruby. Вона однаково добре працює на Windows, Linux, Mac OS X, і з Ruby версіями 1.8 та 1.9.

Інсталяція wxRuby2
Є два методи інсталяції wxRuby2:

  • Використовуючи Rubygems для встановлення бінарного gem-у(без залежностей)

  • Із вихідних кодів



Для більшості людей на більшості операційних систем перший метод є зручнішим і швидшим. Для цього достатньо у командному рядку виконати:
gem install wxruby


Слід зазначити, що при написанні власних додатків використовуючи wxRuby, встановлену із gem-ів, ви повинні попередньо завантажити(не обов'язково для ruby >= 1.9 ) бібліотеку rubygems. Це можна зробити кількома способами:

  • Запустити ruby з аргументом -rubygems. Наприклад: ruby -rubygems my_wxruby_script.rb

  • Встановити RUBYOPT змінну оточення як -rubygems

  • Додати на початку програми рядок require 'rubygems'


Розпочнемо з просто прикладу. Покажемо вікно з кнопкою "Press me", при натисканні на яку відобразиться діалогове повідомлення.
# -*- encoding: utf-8 -*-

# Підключаємо бібліотеку wxruby2
require 'wx'

# Створюємо свій клас спадкоємець Wx::Frame з усіма потрібними нам елементами, а потім використовуємо його.
class HelloFrame < Wx::Frame
def initialize
super(nil, :title => 'Hello World!')
button = Wx::Button.new(self, :label => 'Press me') # Створюємо кнопку. За допомогою посилання self вона сама себе додасть у фрейм

evt_button(button.get_id, :bt_evt) # У випадку натиснення викликаємо bt_evt()
show # показуємо вікно
end

def bt_evt
Wx::MessageDialog.new(self, "Hello world!", "Test", Wx::OK).show_modal # створюємо діалог з однією кнопкою OK і відображаємо його за допомогою show_modal()
end
end

class HelloApp < Wx::App
def on_init
HelloFrame.new # створюємо екземпляр нашого класу
end
end

app = HelloApp.new
app.main_loop() # Запускаємо головний цикл Wx. З цього моменту програма очікує на різні події.



У результаті будемо мати таке віконечко:


В даний час API представляє собою прямий порт wxWidgets C++ інтерфейсу. Місцями цей інтерфейс є трохи аляповий, завдяки своїй довгій історії. В майбутньому розробники планують додати Ruby-специфічний шар поверх базового Wx API, аналогічно тому як це зроблено у FXRuby для Fox. Це розширене API буде простіше у використанні і орієнтуватиметься на Ruby-стиль. Крім того розробники створили підпроект wxSugar(який може використовуватись поверх wxRuby) у якості випробувального полігону для покращень синтаксису.

У гем пакеті wxRuby є досить багато прикладів роботи з різноманітними віджетами, тому цього цілком вистачить, для демонстрації можливостей Ruby + wxWidgets.
У мене це /opt/lib/ruby/gems/1.9.1/gems/wxruby-ruby19-2.0.0-x86-linux/samples


Посилання:
http://wxruby.rubyforge.org
http://www.wxwidgets.org/
http://ru.wikipedia.org/wiki/WxWidgets

середа, 19 серпня 2009 р.

Quake Live for Linux

Те, що так довго очікувалося, нарешті збулося! Хай гримлять литаври і б’ють в барабани, хай нічні феєрверки не згасають цілу ніч, а вдень падають на землю важким дощем.Збулось!

Twitter доставив приємну звісточку:
QUAKE LIVE is back online, now with Mac & Linux support! Read more at www.quakelive.com/forum/showthread.php?t=31851


Протестовано на Ubuntu 9.04 з Firefox 3.0.13.
Плагін для Firefox оформлений у вигляді xpi-файла.

I18N. Підтримка української мови в Ruby і Ruby On Rails

Ukrainian language support for Ruby & Ruby and Rails | Підтримка української мови для Ruby та Ruby on Rails

Що це і кому це може знадобиться?

Ukrainian – бібліотека повноцінної підтримки української мови(форматування дати та часу, плюралізації та інтернаціоналізації вцілому)

Ruby on Rails

Пакет мість в собі переклади стандартних бібліотек: ActionView, ActiveRecord, ActiveSupport, а також підтримку плюралізацій для таких методів як distance_of_time_in_words та distance_of_time_in_words_to_now

неділя, 9 серпня 2009 р.

Плани на Ruby 1.9.2


Фінальна версія Ruby 1.9.2 запланована на кінець 2009 року (25 грудня).
Вже зараз ви можете спробувати перший попередній реліз, який був представлений 17 липня, під час японської конференції Ruby Kaigi 2009.

Наступні цікаві особливості будуть включені до 1.9.2, якщо вони будуть реалізовані вчасно до заморожування (25 вересня 2009 року, 1.9.2 preview release 3):


Крім того розробники обіцяють оптимізувати інтепритатор YARV а також внести зміни до стандартної бібліотеки. Докладніше тут.

субота, 8 серпня 2009 р.

Ruby for System Administration → Ruby-inotify

Inotify - це підсистема ядра Linux, яка дозволяє отримувати повідомлення про зміни у файловій системі. У основне ядро була включена починаючи з 2.6.13. Основна сфера використання - в системах пошуку (наприклад Beagle), таким чином програмі-індексатору не потрібно сканувати всю файлову систему кожні кілька хвилин.

ruby-inotify - це Ruby інтерфейс для доступу до системних викликів Linux Inotify.
Дозволяє виявляти, якщо файл був відкритий, закритий, переміщений, видалений, модифікований і багато чого іншого.


Доступні події:
ACCESS - звернення до файлу(читання).
MODIFY - файл був змінений(запис).
CREATE - файл був створений.
ATTRIB - змінені метадані (права, дата створення/редагування, розширені атрибути, і т.д.).
CLOSE_WRITE - файл, відкритий для запису, був закритий.
CLOSE_NOWRITE - файл, не відкритий для запису, був закритий.
OPEN - файл був відкритий.
MOVED_FROM - файл був переміщений від слідкування.
MOVED_TO - файл був переміщений до слідкування.
DELETE - файл був видалений.
DELETE_SELF - відслідковуваний файл/каталог був видалений.
CLOSE - IN_CLOSE_WRITE | IN_CLOSE_NOWRITE
MOVE - IN_MOVED_FROM | IN_MOVED_TO
ALL_EVENTS - будь-яка з подій.
UNMOUNT - файлова система була відмонтована.
Q_OVERFLOW - черава inotify переповнена.
IGNORED - відслідковуваний файл був автоматично видалений, тому що файл був видалений або файлова система розмонтована.
ISDIR - подій відбулася відносто каталогу.


Процес інсталяції з вихідних кодів є дуже простим:
$ wget http://dinhe.net/~aredridel/projects/ruby/ruby-inotify-0.0.2.tar.gz
$ tar xzvf ruby-inotify-0.0.2.tar.gz
$ cd ruby-inotify-0.0.2/
$ rake1.9.1
$ sudo make install


Як воно працює?
У каталозі examples міститься скрипт watcher.rb, який є простим прикладом роботи з ruby-inotify.
#!usr/bin/ruby

require 'inotify'
require 'find'

i = Inotify.new

t = Thread.new do
i.each_event do |ev|
p ev.name
p ev.mask
end
end

raise("Specify a directory") if !ARGV[0]

Find.find(ARGV[0]) do |e|
if ['.svn', 'CVS', 'RCS'].include? File.basename(e) or !File.directory? e
Find.prune
else
begin
puts "Adding #{e}"
i.add_watch(e, Inotify::CREATE | Inotify::DELETE | Inotify::MOVE)
rescue
puts "Skipping #{e}: #{$!}"
end
end
end

t.join

При створенні/видаленні/переміщені будь-якого файлу чи каталогу на екран буде виведене його ім’я і маска.
Як бачите все доволі просто.

Запустимо скрипт:
$ ruby1.9.1 watcher.rb .


Створимо файл з іменем test.txt і подивимось на результат роботи скрипта
результат:
"test.txt"
256

Створимо каталог з іменем test
результат:
"test"
1073742080

Видалимо файл test.txt
результат:
"test.txt"
512

Видалимо каталог test
результат:
"test"
1073742336


Де застосовувати?

Та де завгодно! Наприклад на мому домашньому сервері крутиться скрипт, який слідкує за каталогом /mnt/smb/downloads (у який користувачі через ssh скачують файли з інтернету) і виводить час створення або видалення файлів на web-сторінку.

Посилання:

Ruby 1.9.1 on Ubuntu Jaunty

В репозиторії Ubuntu Jaunty немає Ruby 1.9.1, а лише пакети версії 1.9.0.
Тому ви повинні збирати його з вихідного коду або використовувати сторонні репозиторії.

Починаючи з версії 1.9.1. у комплект Ruby також входить Rubygems, так сказати Just Work™.


Встановлення із вихідних кодів

Спочатку встановдюємо необхідні залежності:
sudo apt-get install build-essential libssl-dev libreadline5 libreadline5-dev zlib1g zlib1g-dev


Далі скачуємо найсвіжішу версію Ruby 1.9.1 з офіційного сайту.
Компілюємо і встановлюємо:
./configure --prefix=/opt/ruby191
make
make test
sudo make install


І на сам кінець для зручності створимо відповідні посилання:
sudo ln -s /opt/ruby191/bin/ruby /usr/local/bin/ruby1.9.1
sudo ln -s /opt/ruby191/bin/testrb /usr/local/bin/testrb1.9.1
sudo ln -s /opt/ruby191/bin/rake /usr/local/bin/rake1.9.1
sudo ln -s /opt/ruby191/bin/ri /usr/local/bin/ri1.9.1
sudo ln -s /opt/ruby191/bin/rdoc /usr/local/bin/rdoc1.9.1
sudo ln -s /opt/ruby191/bin/irb /usr/local/bin/irb1.9.1
sudo ln -s /opt/ruby191/bin/gem /usr/local/bin/gem1.9.1
sudo ln -s /opt/ruby191/bin/erb /usr/local/bin/erb1.9.1


Готово!
$ ruby1.9.1 -e 'puts RUBY_DESCRIPTION'
ruby 1.9.1p243 (2009-07-16 revision 24175) [i686-linux]



Встановлення з репозиторію Ubuntu on Rails PPA

Тим, хто вже тестує Ubuntu on Rails PPA спеціальний бонус від Antono Vasiljev
Додаємо новий репозиторій:
deb http://ppa.launchpad.net/ubuntu-on-rails/ppa/ubuntu karmic main
deb-src http://ppa.launchpad.net/ubuntu-on-rails/ppa/ubuntu karmic main

$ sudo apt-get update
[...]
W: GPG error: http://ppa.launchpad.net jaunty Release: Слідуючі підписи не можуть бути перевірені, тому що, публічний ключ відсутній: NO_PUBKEY B6C6326781C0BE11
[...]

Додаємо публічний ключ:
gpg --keyserver keyserver.ubuntu.com --recv B6C6326781C0BE11
gpg --export --armor B6C6326781C0BE11 | sudo apt-key add -

Встановлюємо Ruby 1.9.1:
sudo apt-get install ruby1.9.1 ri1.9.1 rdoc1.9.1


Також можете зібрати пакет самостійно як це описано тут.

четвер, 23 липня 2009 р.

Matz Has a Mac!

Ця фотографія підняла мені настрій :)

Для тих хто не в курсі, це Юкіхіро Мацумото(Yukihiro Matsumoto) також відомий як Matz, творець мови програмування Ruby.

>>> Подробиці

Ubuntu on Rails


Недавно на просторах Launchpad.net була створена команда Ubuntu on Rails.

Ціль команди полягає у підтриманні пакетів для розробки на Ruby/Rails. Першочергово це актуальні версії rubygems і passenger.
В команді беруть участь хлопці з Brightbox, які досі підтримують пакети passenger, nginx-passenger, ruby-ee для Ubuntu і Debian.

>>> Подробиці

вівторок, 21 липня 2009 р.

Mechanize + Cookie + вКонтакте. Частина 6



Куки(від англ. Cookie - печиво) - фрагмент даних, який створюється веб-сервером і зберігається на комп'ютері користувача у вигляді файлу, який веб-клієнт(зазвичай веб-браузер) кожен раз пересилає веб-серверу у HTTP-запиті при спробі відкрити сторінку відповідного сайту. Застосовується для збереження даних на стороні користувача, на практиці зазвичай використовується для:

  • автентифікації користувача;

  • зберігання персональних даних і налаштувань користувача;

  • відслідковування стану сесії доступу користувача;

  • ведення статистики про користувачів.



Бібліотека WWW::Mechanize надає зручний інтерфей для роботи з куками - WWW::Mechanize::CookieJar. Цей клас використовується для керування куками, які були повернуті з якого-небудь конкретного сайту. Крім того дозволяє зберігати куки до файлу, з можливістю використовувати його пізніше(наприклад, для автентифікації користувача на сайті без необхідності вводу логіна і пароля). Доступні наступні формати для зберігання/завантаження куки: :yaml <- YAML структура і :cookiestxt <- Mozilla у форматі cookies.txt.


Повернемося до попередньої статті і додамо можливість авторизації за допомогою пересилання куки вебсерверу.
Авторизація здійснюється через надсилання куки 'remixpassword'. Значення 'remixpassword', встановлюється в результаті успішної авторизації, і може бути використане для продовження ідентифікатора сесії('sid').
Цей метод можна використати і у UserAPI при запиті до http://login.userapi.com/auth?login=auto&site=2.

Тут я не буду приводити повний лістинг. А лише доповню код з попередньої статті.
Для початку потрібно авторизуватися на сайті ВКонтакте і записати куки у файл на диску. Для цього створимо новий метод save_cookie().
def save_cookie(cookie_file)
@a.cookie_jar.save_as(cookie_file, format = :cookiestxt)
end

Якщо авторизація пройшла успішно, записуємо куки у файл cookie.txt

if login_force(id, email, pass)
puts "Successfully Authentication"
save_cookie('cookie.txt')
else
puts "Authentication Error"
end


Далі ми будемо авторизовуватись за допомогою цією куки. Створимо метод login_auto()

def login_auto(uid, cookie_file)
@a.cookie_jar.load(cookie_file, format = :cookiestxt)
login_page = @a.get('http://vkontakte.ru/')
return /http:\/\/vkontakte\.ru\/id(\d+)/ === login_page.uri.to_s ? ($1 == uid ? true : false) : false
end


Надалі у нас нема необхідності використовувати метод login_force(). Замість нього використовуємо login_auto()

if login_auto(id, 'cookie.txt')
puts "Successfully Authentication"
else
puts "Authentication Error"
end


Якщо комусь цікаво про плюси авторизації за допомогою куки(в т.ч. і на сайті ВКонтакте), залишайте коментарі.

вівторок, 14 липня 2009 р.

розробка.com


Розробка — молодий соціальний сайт для розробників, побудований по моделі Хабрахабри. Сайт орієнтований на українську аудиторію розробників. Наразі проет ще досить малоактивний, але маю надію в майбутньому до нього буде залучатися все більше і більше людей.
Це перша стаття на Розробці опублікована мною, проба пера так сказати. Прошу не судити строго. Можливо комусь вона буде цікавою. Ця стаття була написана мною у цьому блозі ще у вересні 2007 року. Хоча і досі не втратила своєї актуальності.

пʼятниця, 10 липня 2009 р.

Mechanize + Nokogiri + вКонтакте. Частина 5


Ніхто не помітив зовнішніх змін. Положення тіла пацієнта вКонтакте на операційному столі залишалось незмінним. Але мушу повідомити неприємну новину: ідентифіковано мутації. Тому всі попередні дослідження [1][2][3][4] вважаються недійсними. Нічого... не треба падати духом.
Їжачки плакали і кололись, але продовжували кохатися з кактусами! ©

Nokogiri - це парсер HTML, XML, SAX. Серед його численних можливостей можна виділити можливість використання XPath(XML Path Language) і CSS3 селекторів для пошуку.
Крім того Nokogiri має сумісний з Hpricot синтаксис XPath та CSS.
На даний час Nokogiri найшвидший парсер XML для Ruby.
Mechanize для синтаксичного розбору html використовує саме Nokogiri.

Приклад використання:

Підключення необхідних бібліотек
require 'nokogiri'
require 'open-uri'

Завантаження HTML сторінки, використовуючи open-uri, який йде з Ruby
doc = Nokogiri::HTML(open('http://www.google.com/search?q=ruby-ua'))

Пошук вузлів за допомогою CSS3 селекторів
doc.css('h3.r a.l').each{|link| puts link.content}

Пошук вузлів за допомогою XPath
doc.xpath('//h3/a[@class="l"]').each {|link| puts link.content}


Автор рекомендує використовувати XPath селектори для вищої швидкодії - пошук CSS швидкий ніж у Hpricot, але не такий швидкий.
Nokogiri::XML::Node#xpath(*paths) - функція пошук вузлів(nodes) для XPath шляхів(paths). Шлях повинен бути одним або декількома XPath запитами(queries).
Цікавоє можливістю є задання власних функцій XPath із використанням регекспів(regexp). Для цього потрібно створити класс і застосувати функцію # яку хочете визначити. Наприклад:

node.xpath('.//tr[mess(., "mess\d+")]', Class.new {
def mess node_set, regex
node_set.find_all { |node| node['id'] =~ /#{regex}/ }
end
}.new)


Така функція знайде всі вузли виду:
<tr id="mess127">[...]</tr>
<tr id="mess128">[...]</tr>
<tr id="mess129">[...]</tr>


вКонтакте!?
У зв'язку зі змінами на сайті vkontakte.ru мої попередні дописи про вконтакте втратили свою актуальність. Не знаю скільки часу буде працездатним цей код. Але суть в іншому: показати принципи роботи з Mechanize і Nokogiri на реальному прикладі.
Що ж робить нищеприведений код?

  • Авторизація через надсилання email-адреси та пароля користувача; (login_force)

  • Отримання останніх приватних повідомлень; (get_messages)


# -*- encoding: utf-8 -*-
require 'mechanize' # recommended 0.9.2

@a = WWW::Mechanize.new{|agent|
agent.user_agent_alias = 'Linux Konqueror'
agent.follow_meta_refresh = true
}

# Authorisation by submitting email and password (Login)
#
def login_force(uid, email, pass)
login_page = @a.get('http://vkontakte.ru/login.php')
login_form = login_page.form_with(:name => "login")
login_form.email = email
login_form.pass = pass
user_page = login_form.submit
return /http:\/\/vkontakte\.ru\/id(\d+)/ === user_page.uri.to_s ? ($1 == uid ? true : false) : false
end

# Getting private messages list for current user
#
# Structure of each entry of resulting array
# [0] - message from
# [1] - message date
# [2] - message title
# [3] - message_body
#
def get_messages
url = 'http://vkontakte.ru/mail.php'
messages_page = @a.get(url)
node = Nokogiri::HTML(messages_page.body)
message = node.xpath('.//tr[mess(., "mess\d+")]', Class.new {
def mess node_set, regex
node_set.find_all { |node| node['id'] =~ /#{regex}/ }
end
}.new)
message_from = message.xpath('//td[@class="messageFrom"]/div[@class="name"]/a').map {|link| /\/id(\d+)/.match(link['href'])[1]}
message_date = message.xpath('//td[@class="messageFrom"]/div[@class="date"]').map {|link| link.content}
message_title = message.xpath('//a[@class="new messageSubject"]/span').map {|link| link.content}
message_body = message.xpath('//a[@class="new messageBody"]').map {|link| link.content}
messages = Array.new
messages = [message_from, message_date, message_title, message_body].transpose
return messages
end

id = "12345678"
email = "username@example.com"
pass = "secret"

if login_force(id, email, pass)
puts "Successfully Authentication"
get_messages.each {|message|
puts "[#{message[1]}]: #{message[0]}"
puts message[2]
puts message[3]
puts "==="
}
else
puts "Authentication Error"
end

Blogger: Створи власний безкоштовний блог?

Весь час перебування в Blogger мені не вистачало однієї корисною фічі з ЖЖ. І нарешті цей прикрий пробіл закритий.
За посиланням можна прочитати як створювати розширювані короткі описи повідомлень, такий собі аналог <lj-cut> з ЖЖ.
Доведеться трохи повозитися з шаблоном. Але найважливіше воно працює :)
Не встиг я потішитись обновці, як на і-мейл прийшов лист від Blogger.
А-а-а-а-а!!!!!11 OMG! Хто б міг подумати? Я спамер!!! На жаль або на щастя в Україні немає безпосередньої відповідальності за поширення спаму.
І тепер замість блогу красується заглушка з багатозначним надписом:

Я пам'ятайте, якщо ви читаєте цей пост, значить цей блог не містить потенційного спаму :). Перевірено Великим Ґуґло'м.

Якщо комусь цікаво, під катом текст листа від Blogger.


Вітаємо!

Ваш блог на: http://ruby-ua.blogspot.com/ ідентифіковано як блог із потенційним спамом. Для вирішення цієї проблеми надішліть запит на перегляд, заповнивши форму на http://www.blogger.com/unlock-blog.g?lockedBlogID=4152168096498110483

Якщо ваш блог не буде переглянуто, його буде видалено через 20 днів, а впродовж цього періоду вашим читачам відображатиметься сторінка попередження. Після отримання запиту ми переглянемо ваш блог і розблокуємо його протягом двох робочих днів. Після того як ваш буде розглянуто та буде виявлено, що він не є спамом, блог буде розблоковано, а повідомлення на вашій панелі керування Blogger більше не відображатиметься. Якщо цей блог не належить вам, нічого робити не потрібно. Це не вплине на будь-які інші ваші блоги.

Ми шукаємо спам, використовуючи автоматичний класифікатор. Автоматичне виявлення спаму є неточним, і час від часу блоги, схожі на ваш, позначаються неправильно. Ми просимо вибачення за цю помилку. Однак за допомогою такої системи ми можемо забезпечити більше місця для зберігання, вищу пропускну здатність і більше технічних ресурсів для таких авторів блогів, як ви, а не для спамерів. Для отримання додаткової інформації див. довідку Blogger: http://help.blogger.com/bin/answer.py?answer=42577

Дякуємо за розуміння та допомогу в боротьбі зі спамом.

Із повагою,

команда Blogger

P.S. Ще одне нагадування: якщо ви не надішлете запит на перегляд вашого блогу, через 20 днів його буде видалено. Перейдіть за цим посиланням, щоб надіслати запит на перегляд: http://www.blogger.com/unlock-blog.g?lockedBlogID=4152168096498110483


Мені от дійсно цікаво: хто і як буде перевіряти rubукраїномовний блог на спам відповідність умовам обслуговування Blogger?

неділя, 5 липня 2009 р.

Ruby for System Administration → Bash quoting

Інколи використовую Ruby для задач системного адміністрування. Ruby з широким набором бібліотек чудово для цього підходить.
Однією з поширених задач є виклик зовнішніх команд Linux, передачі їм різноманітних параметрів, отримання і обробки результатів. І тут ви обов'язково стикнетеся з маскуванням символів в bash.


Маскування(quoting) в bash використовується для відміни спеціального значення для команд інтерпрeтатора визначених символів або слів.
Маскування можна використовувати для скасування специфічної обробки спеціальних символів, для запобігання розпізнавання зарезервованих слів, а також для запобігання підстановки параметрів.
Метасимвол - це символ, який розділяє слова, якщо він не замаскований. Є одним з наступних символів:
| & ; ( ) < > пробіл табуляція

Існує три механізми маскування:
символ маскування (escape character), одинарні лапки і подвійні лапки.

Незамаскована зворотна коса риска (\) є символом маскування(escape character). Вона вимагає використовувати наступний за нею символ(за винятком переведення рядка) буквально.

Усі символи в одиночних лапках (') використовуються буквально. Символ одиночної лапки(апостроф) не повинен вказуватися між лапках, навіть якщо його випереджає зворотна коса.

Символи в подвійних лапках(") використовуються буквально, за виключенням $, !, ` і \
Зворотна коса має спеціальне значення тільки якщо після неї йде один з спеціальних символів.

З точки зору програмування, маскування з допомогою одинарних лапок є найпростішим (але не дозволяє маскувати символ одинарних лапок). Тоді як з допомогою зворотної косої - найскладніший.
Ми не шукаємо простих шляхів :)

Напишемо просто функцію, яка отримуватиме cтроку і повертатиме масковану строку, придатну для використання в bash.
Зауважу, код буде працювати тільки в версіями Ruby вище 1.9, оскільки в Regexp використовується нова можливість Oniguruma - іменовані групи(named groups).
#!/usr/bin/env ruby1.9
# -*- encoding: utf8 -*-

def quote_for_bash(text)
text = text.dup
text.gsub!( /(?<backslash>\\)/, '\\\\\k<backslash>' )
text.gsub!( /(?<space>\s)/, '\\\\\k<space>' )
text.gsub!( /(?<double-quotes>")/, '\\\\\k<double-quotes>' )
text.gsub!( /(?<single-quotes>')/, '\\\\\k<single-quotes>' )
text.gsub!( /(?<apostrophe>`)/, '\\\\\k<apostrophe>' )
text.gsub!( /(?<brackets>[()<>])/, '\\\\\k<brackets>' )
text.gsub!( /(?<semicolon>;)/, '\\\\\k<semicolon>' )
text.gsub!( /(?<exclamation-mark>!)/, '\\\\\k<exclamation-mark>')
text.gsub!( /(?<ampersand>&)/, '\\\\\k<ampersand>' )
text.gsub!( /(?<dollar-sign>\$)/, '\\\\\k<dollar-sign>' )
text.gsub!( /(?<number-sign>#)/, '\\\\\k<number-sign>' )
text.gsub!( /(?<vertical>\|)/, '\\\\\k<vertical>' )
return text
end


Задамо текст, який, наприклад, в майбутньому будемо використовувати як параметр для якоїсь команди:
text = %{#<b>$a;say "hello" & |Profit!|  -  (`1$)</b>}


Початковий текст матиме такий вигляд:
puts text
#<b>$a;say "hello" & |Profit!| - (`1$)</b>


Маскований текст буде таким:
puts quote_for_bash(text)
\#\<b\>\$a\;say\ \"hello\"\ \&\ \|Profit\!\|\ \ -\ \ \(\`2\$\)\</b\>

понеділок, 29 червня 2009 р.

Redcar - аналог Textmate для Linux


Ті з вас хто хоч раз бачив Railscasts, думаю в курсі про Mac OS'ісовський текстовий редактор TextMate - Великий фетиш і Ідол всіх програмістів на Ruby під Mac. Особисто я був у захваті від побаченого. Але нажаль розробники TextMate не подумали про нещасних Linux користувачів, які готові віддати свої 57$. Так ось, схоже у нас тепер з'явився аналог - Redcar, автором якого є Daniel B. Lucraft'а.
Ось що говорить сам автор про свій проект:
Redcar - текстовим редактором для програмістів з відкритим вихідним кодом для Gnome(Linux). Він призначена для забезпечення сумісності з Textmate bundles(робота триває), і написаний майже повністю на Ruby, і з використанням Vala для швидкодії. Redcar все ще перебуває в зародковому стані...

Зараз функціонує вже 75% всіх можливостей TextMate.
Детальна (і що головне, робоча) інструкція як зібрати його під Ubuntu 9.04 лежить у git'і.
Дуже хочеться що б проект продовжував розвиватися.

понеділок, 22 червня 2009 р.

Merb tutorial in Ukrainian


На сайті молодої україномовної соціальної IT спільноти Розробка.com з'явився туторіал по Merb. Підручник охоплює як створювати прості програми за допомогою Merb, haml і DataMapper.

неділя, 14 червня 2009 р.

URL Encoding/Decoding with Ruby 1.9

Encode and decode a string for a URL with Ruby 1.9 (according to RFC 3986 and RFC 3629).

# URL encoded text:
enc_str = "http://uk.wikipedia.org/wiki/%D0%84%D0%B2%D1%80%D0%BE%D0%BF%D0%B0"

# Decode:
require 'cgi'
dec_str = CGI::unescape(enc_str)
=> http://uk.wikipedia.org/wiki/Європа
dec_str.encoding
=> #<Encoding:UTF-8>


# URL decoded text:
dec_str = "Декодований текст"

# Encode:
require 'cgi'
enc_str = CGI::escape(dec_str)
=> "%D0%94%D0%B5%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B9+%D1%82%D0%B5%D0%BA%D1%81%D1%82"
enc_str.encoding
=> #<Encoding:US-ASCII>

Ruby 1.9 and R-Bus

Намагаючись завести зв'язку Ruby 1.9 + D-Bus, натрапив на проект R-Bus.
З офіційної сторінки бубліотеки:
R-Bus is a native implementation of the D-Bus protocol, with these goals in mind:Ruby + standard library is the only dependencies, a rubyish API, approach and way of doing things, complete client functionality and a comprehensive test suite.

Останньою новиною проетку є Ruby 1.9.1 support in trunk датована 5 квітня 2009 року.
Як виявилось пізніше версія з транку не працює з Ruby 1.9.1. Тому доведеться накладати патч. Перевірено, він сумісний не тільки з версією 1.9.1 Ruby, а й попередніми. Приємно, що автором патчу є наш земляк Sergey Yanovitsky, за що йому велике Дякую. Хоча і не всі функції працездатні :(.


Install Ruby 1.9.1 from sources:
$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p129.tar.gz
$ tar xzvf ruby-1.9.1-p129.tar.gz
$ mkdir ruby1.9
$ cd /home/mama/ruby-1.9.1-p129
$ ./configure --prefix=/home/mama/ruby1.9
$ make
$ make install
$ PATH=/home/mama/ruby1.9/bin:$PATH
$ ruby -v
ruby 1.9.1p129 (2009-05-12 revision 23412) [i686-linux]

Get the R-Bus code from Subversion with:
$ svn checkout svn://rubyforge.org/var/svn/rbus/trunk rbus
$ cd rbus

Get Ruby 1.9 and Rspec 1.2.2 support patch
wget http://rubyforge.org/tracker/download.php/3277/12588/25318/4487/ruby-1.9_rspec-1.2.2_support.diff

Apply patch:
$ patch -p0 < ruby-1.9_rspec-1.2.2_support.diff

Install rbus:
$ ruby setup.rb

Example:
require 'rbus'
session_bus = RBus.session_bus
rb_player = session_bus.get_object('org.kde.amarok', '/Player')
uri = rb_player.GetMetadata()

Посилання:
R-Bus API Docs, Tutorial and more

субота, 13 червня 2009 р.

Ruby D-Bus

Цей запис описує створення простого D-Bus клієнта до аудіопрогравача Amarok 2 за допомогою Ruby.

Що таке D-Bus і принцип його роботи
D-Bus - це система міжпроцесної взаємодії, яка надає додаткам декілька шин для передачі повідомлень.
D-Bus є частиноє проекту freedesktop.org. Вона володіє високою швидкодією, інтегрується з багатьма робочими середовищами. D-Bus доступна для GLib, Java, Mono, Qt, Python, Ruby і є прозорою для мережі.
D-Bus надає системі декілька шин:
  1. Системна шина. Створюється під час старту демона. З її допомогою відбувається спілкування різноманітних демонів, вона практично недоступна для додатків користувача.
  2. Сесійна шина. Створюється для користувача, авторизованого у системі. Для кожної такої шини запускається окрема копія демона, через неї спілкуються додатки, з якими працює користувач.

Кожне повідомлення D-Bus має свого відправника і одержувача, а їхні адреси називаються шляхами об'єктів, оскільки D-Bus вважає, що кожен додаток складається із набору об'єктів, а повідомлення пересилається не між додатками, а між об'єктами цих самих додатків.
Кожен об'єкт може підтримувати один або більше інтерфейсів, які представленні у вигляді іменованих груп методів і сигналів.
D-Bus також передбачає концепцію сервісів. Сервіс - унікальне місцезнаходження додатка на шині. При запуску додаток реєструє один або декілька сервісів, якими воно буде володіти до тих пір поки самостійно не звільнить. Ніякий інший додаток, що претендує на той же сервіс, зайняти його не зможе. Іменується сервіси аналогічно інтерфейсам.
У кожного об'єкта своє унікальне ім'я, яке виглядає як шлях в файловій системі. Наприклад, /org/kde/amarok/Player

Інсталяція ruby-dbus
Бібліотеку Ruby D-Bus можна встановити за допомогою команди:
$ gem install ruby-dbus

Це все! Тепер можемо перейти до використання...

Використання бібліотеки в Ruby

Для того що використовувати бібліотеку ви повинні включити її у вашу програму за допомогою
require 'dbus'

Приєдняння до шини
bus = DBus::SystemBus.instance
bus = DBus::SessionBus.instance

відповідно, або до системної шини, або до сесійної.

Виклик методу
Наприклад ми хочемо отримати доступ до об'єкта клієнта аудіопрогравача Amarok через шину сесій. Amarok надає сервіс з іменем org.kde.amarok
rb_service = bus.service("org.kde.amarok")

Тепер у нас є маніпулятор для сервісу і ми знаємо, що він експортує об'єкт /Player. Отримати доступ до цього об'єкта можна за допомогою методу object:
rb_player = rb_service.object("/Player")

rb_player.introspect

Нагадаю, об'єкти D-Bus мають інтерфейси, а інтерфейси в свою чергу мають методи. Далі отримуємо доступ до цих методів:
rb_player_iface = rb_playes["org.freedesktop.MediaPlayer"]
rb_player_iface.Pause

Як ви можете бачити, коли ви хочете викликати метод об'єкта, ви повинні отримати правильний інтерфейс. Це трохи втомлює, тому ми маємо наступне посилання, яке робить те ж саме, що й раніше:
rb_player.default_iface = "org.freedesktop.MediaPlayer"
rb_player.Pause

Деякі D-Bus об'єкти забезпечують доступ до властивостей. Вони доступні, як хеш:
rb_player_iface.GetMetadata
=> [{"album"=>"www.reconstructionmusic.org", "artist"=>"allMeadow & Rob Costlow", "arturl"=>"", "audio-bitrate"=>350, "audio-samplerate"=>44100, "comment"=>"This Amarok theme was made by allMeadow & Rob Costlow especially for Amarok. You can check out more of their projects at Magnatune.com or at www.reconstructionmusic.org", "genre"=>"Instrumental", "location"=>"file:///usr/share/kde4/apps/amarok/data/first_run_jingle.ogg", "mtime"=>40000, "rating"=>0, "time"=>40, "title"=>"Art Of Nations (Amarok Theme)", "tracknumber"=>1, "year"=>"2010"}]


Замість висновків
Знайти докладну інформацію про D-Bus API конкретних програм буває непросто, але Google завжди буде відданим супутником у ваших дослідженнях.

На сьогодні це все, малята :)

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