вівторок, 29 жовтня 2013 р.

Magento XML-RPC API і Ruby

Після написання першої статті Magento REST API і OAuth в Ruby, захотілося продовжити вивчення можливостей Magento API.
Весь сир-бор через те, що можливості REST в Magento просто жалюгідні.
На сьогодні Magento підтримує всі найбільш поширені способи доступу до API сайтів: REST, XML-RPC, SOAP.

Magento SOAP/XML-RPC API дає вам можливість керувати своїми магазинами електронної комерції, забезпечуючи методи для роботи з ресурсами, такими як клієнти, категорій, продукти і замовлення.

Про SOAP можна говорити багато і довго.
Для мене основними мінусами стали складність протоколу і відсутність вбудованої підтримки в Ruby.
Натомість стандарт XML-RPC зачарував мене своєю надзвичайною простотою.
В базову поставку Ruby вже входить бібліотека для роботи з XML-RPC, відповідно вам не доведеться замислюватися про структуру запитів і обробку відповідей в XML.

Тому саме XML-RPC в основному і буде присвячена ця стаття.
Не буду зупинятися на питанні, що таке XML-RPC і навіщо він потрібен. У мережі багато статей на цю тему.

Просто постараюся коротко показати, яким простим способом можливе створення клієнта до XML-RPC веб-сервісу на Ruby.
require 'xmlrpc/client'

config = {
  api_user: 'user',
  api_key:  'secret',
  host:     'example.com',
  path:     '/api/xmlrpc',
  port:     80,
}
client = XMLRPC::Client.new(config[:host], config[:path], config[:port])

# If somestuff requires api authentification,
# we should get session token
session = client.call('login', config[:api_user], config[:api_key])

parent_id = 1
store_view = 1
client.call('call', session, 'catalog_category.tree', [parent_id , store_view])

# If you don't need the session anymore
client.call('endSession', session)

Все просто: ми підключаємося до сервера, отримуємо ключ сесії і виконуємо запити.

Документацію по всіх запитах Magento API можна знайти на офіційному сайті.
XML-RPC підтримується тільки першою версією Magento API.

неділя, 20 жовтня 2013 р.

Magento REST API і OAuth в Ruby

У цій статті я хочу поділитися прикладом роботи з Magento REST API використовуючи Ruby і oauth gem. У свій час пошуки подібного ні до чого не привели.

Докладна документація по Magento REST API тут.

Реєстрація та уповноваженому додатку


Отже, приступимо. Першим ділом, потрібно отримати всі потрібні параметри для авторизації. Зокрема ключі consumer_key і consumer_secret. І, власне хост(magentohost), на якому встановлене Magento.

Скажу відразу, налаштування платформи Magento для REST API не розглядається в рамках цієї статті.

пʼятниця, 13 вересня 2013 р.

Зі святом, програмісти!

П'ятниця 13-го. День програміста. Програмістів з відьмами об'єднує не тільки бубен для магічної тряски, а і святкова п'ятницю для шабашу.
Зі Святом, товариші!

Наскільки часто буває такий збіг?
Відповідь під катом.

понеділок, 15 липня 2013 р.

Книга по Ruby 2.0

Алекcандр Круглов виклав у вільний доступ книгу "Ruby" по мові програмування Ruby 2.0.

Якщо я не помиляюся, це перша опенсорс книга про Ruby російською мовою.

Текст книги у форматі PDF доступний за наступним посиланням. Зі змістом можна ознайомитися тут.

Книгу можна зібрати з вихідних кодів:
  1. Встановити Ruby.
  2. Встановити необхідні пакети: gem install redcarpet.
  3. Завантажити скрипт для перетворення Markdown в LaTeX.
  4. Встановити XeLaTeX.
  5. Завантажити стиль.
  6. Зібрати pdf: xelatex book.tex (за замовчуванням використовуються шрифти сімейства Liberation).

>>> Новина взята з LOR.

вівторок, 30 квітня 2013 р.

Отримання улюблених аудіозаписів з Last.fm

Почитав тут статтю Получение любимых аудиозаписей с pandora.com, подумав і придумав subj.
Отже, з Last.fm будемо отримувати список назв пісень і виконавців, потім за допомогою API ВКонтакте будемо їх скачувати.

Крок 1. Йдем на Last.fm, і витягуємо список улюблених пісень користувача.

Для тих хто не знає, Last.fm має API, що дозволяє будь-якому користувачеві створювати свої власні програми з використанням даних Last.fm. Для роботи з API потрібно отримати API Key і Secret. Йдемо на http://www.last.fm/api і створюємо новий аккаунт для некомерційного використання.

ruby-lastfm - інтерфейс для Web-сервісів Last.fm v2.0.
Тепер нам потрібно отримати token:
lastfm = Lastfm.new(lastfm_api_key, lastfm_api_secret)
lastfm_token = lastfm.auth.get_token

Далі нам пропонують відкрити 'http://www.last.fm/api/auth/?api_key=xxxxxxxxxxx&token=xxxxxxxx' і надати права додатку.

Спробуємо змоделювати цей запит. Але спочатку потрібно авторизуватися на сайті Last.fm за допомогою імені і паролю. Використовуємо бібліотеку Mechanize:
mech = Mechanize.new do |a|
  a.user_agent_alias = 'Linux Firefox'
  a.verify_mode = OpenSSL::SSL::VERIFY_NONE
  a.follow_meta_refresh = true
end

login_page = mech.get('https://last.fm/login')
login_form = login_page.form_with(action: '/login')

login_form.username = lastfm_username
login_form.password = lastfm_password

page = login_form.submit

if page.uri.to_s == 'http://www.last.fm/home'
  puts "Login successful!"
else
  puts page.uri.to_s
  exit
end

Якщо авторизація пройшла успішно, надаємо права додатку:
grantaccess_url = "http://www.last.fm/api/auth/?api_key=#{lastfm_api_key}&token=#{lastfm_token}"
grantaccess_page = mech.get(grantaccess_url)

grantaccess_form = grantaccess_page.form_with(action: '/api/grantaccess')
grantaccess_form.submit

Отже, тепер ми можемо витягнути всю цікаву для нас інформацію:
lastfm.session = lastfm.auth.get_session(:token => lastfm_token)['key']
tracks = lastfm.user.get_loved_tracks(user: lastfm_username)

Перший крок пройдений! :)

Крок другий. Пошук і скачування записів з vk.com.
Авторизуємося ВКонаткте:
vk = Vkontakte::Client.new(vk_client_id)
vk.login!(vk_email, vk_password, scope = 'audio')

Використовуємо API функцію пошуку аудіо:
str = "#{track['artist']['name']} - #{track['name']}"
audio = vk.api.audio_search(q: str, sort: 2)[1]

Вона повертає найпопулярніший результат пошуку рядка str (серед аудіозаписів).

Тепер ми знаємо url для скачування. Завантажити можна за допомогою стандартної функції.
path = "#{downloaded_folder}/" + "#{audio['artist']} - #{audio['title']}.mp3"
File.open(path, 'wb') do |saved_file|
  open(audio['url'], 'rb') do |read_file|
    saved_file.write(read_file.read)
  end
end

В результаті вийшов ось такий скрипт:
https://gist.github.com/mamantoha/5488722

Як з ним працювати:
  • Скрипт вимагає встановленого Ruby і гемів mechanize, ruby-lastfm, vkontakte
  • Потрібно отримати ключі для Last.fm(lastfm_api_key, lastfm_secret) і ВКонтакте(vk_client_id)
  • downloaded_folder - директорія, куди буде зберігатися скачана музика
  • lastfm_username і lastfm_password - ваш логін і пароль на Last.fm
  • vk_email і vk_password - ваш логін і пароль на Vk.com

Відповідні параметри прописати в тілі скрипта.

неділя, 24 лютого 2013 р.

Реліз Ruby 2.0.0-p0


У нас свято!
Точно за оперативним планом 24 лютого анонсовано реліз Ruby 2.0.0-p0. Були включені нові можливості, які роблять розробку на Ruby ще приємнішою.

Анонсовані можливості:
  • Уточнення (Refinements) [1]
  • Іменовані аргументи в методах [2]
  • Enumerator#lazy [3]
  • Module#prepend [4]
  • #to_h
  • %i для масивів символів
  • Двигун регулярних виразів змінений на Onigmo [5]
  • Підтримка DTrace [6]

Всі програми, які написані на ruby 1.9 будуть працювати на ruby 2.0, якщо в них не буде особливої магії.

Несумісності:
  • Кодування за замовчуванням для скриптів Ruby стало UTF-8.
  • String#lines, #chars, #codepoints і #bytes тепер повертають Array замість Enumerator.
  • Iconv був остаточно видалений. Він був оголошений застарілим ще для Ruby 1.9.x. Тепер Ви повинні використовувати можливості M17N, такі як String#encode.



В 2.0.0 preview1 був включений чарівних патч, який прискорює роботу Rails в 2.2 рази

субота, 19 січня 2013 р.

Використовуємо life:) API за допомогою Ruby


У цій статті я хочу розповісти Вам, як на мові Ruby налагодити взаємодію з life:) API. Для тих хто не в курсі, life:) — український GSM-оператор мобільного зв'язку.

Все почалося тоді, що коли у офіційному твітері life:) з'явилося повідомлення про додаток "Мій life:)" для Android. Мені відразу стало цікаво — а як вони отримують інформацію, якщо не через свій сайт системи самообслуговування для індивідуальних абонентів Мій life:).

Добрі люди підказали мені, як декомпілювати файл apk. Але це не тема цієї статті.

Трохи покопавшись в горах Java-коду, мені вдалося зрозуміти за яким принципом здійснюється робота з сервісом life:). Варто зауважити, що офіційно нікого API у life:) немає. Тому все нижче написане використовуйте на свій страх і ризик.

Результатом цієї роботи стала бібліотека для Ruby - life-api, яка реалізує деякі методи API. Ви можете знайти її на Github.

Отже, що нам знадобиться щоб виконувати запити?
Розглянемо все по порядку.

Всі запити, включаючи авторизацію виконується до адреси https://api.life.com.ua/mobile.
З кожним запитом передається постійний ключ API accessKeyCode. А applicationKey використовується, як секретний ключ для підписання запиту. Про це трохи пізніше.

вівторок, 8 січня 2013 р.

Встановлення Windows XP на віртуальну машину KVM

Процедури установки і налаштування хост-сервера не розглядається в рамках у цієї статті.

Що дано:
  • Хост-система Ubuntu Server 12.04 LTS
  • KVM
  • Гостьова система Windows XP
Під час інсталяції Windows XP на віртуальну машину KVM стикнувся з дуже низьким дисковим I/O. Метод спроб і помилок бажаний результат був досягнутий.

Створення образу гостьової машини розміром 20 гігабайт у форматі qcow2. Серед підтримуваних форматів QEMU, цей — найбільш універсальний.
$ qemu-img create -f qcow2 -o preallocation=metadata winxp.qcow2 20G

Virtio — це такі спеціальні драйвера, які безпосередньо прокидають фізичне залізо у віртуалку, без емуляції його. Власне це поввино зменшувати навантаження на хост-машину.

У Windows XP, як відомо, немає драйверів Virtio і при установці виникає помилка через відсутність доступу до жорсткого диску.

Для установки драйверів можете використати мій образ дискети Virtio Disk Floppy.
Або створити його власноруч (чи оновити драйвери на дискеті) за допомогою найсвіжіших Virtio Windows Drivers:
$ dd bs=512 count=2880 if=/dev/zero of=viostor-0.1-49-floppy.img
$ mkfs.msdos viostor-0.1-49-floppy.img
$ mkdir /mnt/floppy
$ sudo mount -o loop viostor-0.1-49-floppy.img /mnt/floppy
$ mkdir /mnt/iso
$ sudo mount -o loop virtio-win-0.1-49.iso /mnt/iso
і скопіювати відповідні файли viostor з ISO на дискету, використовуючи мій образ в якості орієнтира.
Для довідки:
wxp — Windows XP
wnet — Windows Server 2003

Далі переходимо до інсталяції віртуальної машини:
$ sudo virt-install -n winxp -r 1024 --disk path=winxp.qcow2,format=qcow2,bus=virtio,cache='writeback' --disk path=viostor-0.1-30-floppy.img,device=floppy -c winxp.iso --video=vmvga --accelerate --os-variant=winxp -v --vnc -w bridge:virbr0

понеділок, 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.