Библиотеку для работы с базами данных ActiveRecord можно использовать и вне Rails.
Посмотреть на github.

Подготовим миграцию БД для создания таблицы. Для простоты в ней всего два строковых поля: day и time:
Попробуем мигрировать:
Отлично. Миграция 001_create_moon_rise_times.rb создала таблицу moon_rise_times с полями day и time.
Для начала создадим тестовый файл lib/test_search.rb ищущий нужные данные на Яндекс.Погода:
Получаем:
Ок, то, что нам нужно.
Теперь надо сохранить полученные данные в БД. Для этого в ActiveRecord::Base есть метод create
Файл, выполняющий главную работу, lib/main.rb:
Запустим его:
Вроде все хорошо.
Посмотрим, что сохранилось в базе с помощью небольшого скрипта lib/test_fetch_data.rb:
Вывод:
Ок! Теперь, запуская каждый день нашу программу можно следить за временем восхода луны!
Задача
Наш тестовый проект будет брать время восхода луны с Яндекс.Погода и сохранять ее в базу данных, используя ActiveRecord. Заодно посмотрим на работу с Nokogiri (хорошую замену hpricot).Структура проекта
Мы будем использовать миграции, файл конфигураций database.yaml, Rakefile, базу данных sqlite (development.sqlite3), в общем, окружение приближенное к любимым рельсам.Посмотреть на github.

Настройка соединения с БД и создание таблицы с помощью миграций
Для удобства конфигурация соединения с БД вынесена в отдельный файл lib/config/database.yml:А соединение с БД в lib/config/environment.rb:
- adapter: sqlite3
- database: lib/db/development.sqlite3
- require 'rubygems'
- require 'active_record'
- require 'yaml'
-
- # Загружаем файл настройки соединения с БД
- dbconfig = YAML::load(File.open(File.join(File.dirname(__FILE__), 'database.yml')))
-
- # Ошибки работы с БД направим в стандартный поток (консоль)
- ActiveRecord::Base.logger = Logger.new(STDERR) # Simple logging utility. logger.rb -- standart lib
-
- # Соединяемся с БД
- ActiveRecord::Base.establish_connection(dbconfig)
Подготовим миграцию БД для создания таблицы. Для простоты в ней всего два строковых поля: day и time:
- class CreateMoonRiseTimes < ActiveRecord::Migration
- def self.up
- create_table :moon_rise_times do |t|
- t.string :day
- t.string :time
- end
- end
-
- def self.down
- drop_table :moon_rise_times
- end
- end
Для выполнения миграции создадим rake-файл.
- require 'lib/config/environment.rb'
-
- # Документация по rake docs.rubyrake.org
- # namespace -- rake.rubyforge.org/classes/Rake/NameSpace.html
-
- namespace :db do
- desc "Migrate the database"
- task :migrate do
- # выполнение всех миграций из lib/db/migrate,
- # метод принимает параметры: migrate(migrations_path, target_version = nil)
- # в нашем случае
- # migrations_path = lib/db/migrate
- # target_version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
- # миграция запускается как rake db:migrate VERSION=номер_версии
- ActiveRecord::Migrator.migrate('lib/db/migrate', ENV["VERSION"] ? ENV["VERSION"].to_i : nil )
- end
- end
Попробуем мигрировать:
- $ rake db:migrate VERSION=1
- (in /home/data/projects/ActiveRecord-without-Rails)
- == CreateMoonRiseTimes: migrating ============================================
- -- create_table(:moon_rise_times)
- SQL (1.0ms) CREATE TABLE "moon_rise_times" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "day" varchar(255), "time" varchar(255))
- -> 0.0019s
- == CreateMoonRiseTimes: migrated (0.0020s) ===================================
- SQL (0.1ms) INSERT INTO schema_migrations (version) VALUES ('1')
Отлично. Миграция 001_create_moon_rise_times.rb создала таблицу moon_rise_times с полями day и time.
Извлечение данных и сохранение их в БД
Теперь надо найти какие-нибудь полезные данные для сохранения в базу данных. Для примера будем брать с сайта Яндекс.Погода время восхода Луны. Также можно вылавливать курсы валют, новости, значение кармы, etc...Для начала создадим тестовый файл lib/test_search.rb ищущий нужные данные на Яндекс.Погода:
- # Файл с небольшим скприптом для тестирования работы nokogiri.
-
- $KCODE = "u"
- require 'jcode'
- require 'rubygems'
- require 'open-uri'
- require 'iconv'
- require 'nokogiri'
-
-
- # Загрузим html-документ
- source = open("pogoda.yandex.ru/26063/details/")
-
- # Создадим объект nokogiri из загруженного документа
- data = Nokogiri::HTML(source)
- # Извлечем все строки html-таблицы с помощью метода search и простого xpath-выражения
- # wiki.github.com/tenderlove/nokogiri
-
-
- =begin
- Фрагмент исходного html-файла, в котором надо найти дату восхода Луны :)
-
- <th class="date" rowspan="4"><b title="">9</b> <span>июля</span></th>
-
- =end
-
- data_html = data.search("th[@class = date]//b").first.inner_html + " " + data.search("th[@class = date]//span").first.inner_html
- puts data_html
-
- =begin
- Фрагмент исходного html-файла, в котором надо найти время восхода Луны в день, определенный выше :)
-
- <td class="dawn-dark" rowspan="4">
- <dl>
- <dt>Восход</dt>
- <dd>04:52</dd>
- <dt>Заход</dt>
- <dd>23:15</dd>
- </dl>
- <img src="//i.yandex.st/weather/i/moon/07.gif" alt="Убывающая луна" title="Убывающая луна">
- </td>
-
- =end
-
- time_html = data.search("td[@class = dawn-dark]//dl//dd").first.inner_html
- puts time_html
Получаем:
- $ ruby lib/test_search.rb
- 10 июля
- 04:53
Ок, то, что нам нужно.
Теперь надо сохранить полученные данные в БД. Для этого в ActiveRecord::Base есть метод create
Файл, выполняющий главную работу, lib/main.rb:
- $KCODE = "u"
- require 'jcode'
- require 'rubygems'
- require 'active_record'
- require 'yaml'
- require 'logger'
- require 'open-uri'
- require 'iconv'
- require 'nokogiri'
-
-
- # загружаем файл environment.rb настройки и соединение с БД
- require File.join(File.dirname(__FILE__), 'config/environment.rb')
-
- # Создаем класс MoonRiseTime, обертывающий таблицу moon_rise_times
- # Ячейки таблицы: day -- тип data, rise_times -- тип time
- #
-
- class MoonRiseTime < ActiveRecord::Base
- end
-
- MoonRiseTime.create do |moon_rise_time|
- # Загрузим html-документ
- source = open("pogoda.yandex.ru/26063/details/")
-
- # Создадим объект nokogiri из загруженного документа
- data = Nokogiri::HTML(source)
- # Извлечем все строки html-таблицы с помощью метода search и простого xpath-выражения
- # nokogiri.org/Nokogiri/XML/Node.html#method-i-inner_html
-
- # :TODO: Привести типы данных к data и time
- # Находим в исходном html дату
- data_moon_rise = data.search("th[@class = date]//b").first.inner_html
- month_moon_rise = data.search("th[@class = date]//span").first.inner_html
-
- # передаем найденные данные методам класса-обертки БД
- moon_rise_time.day = data_moon_rise + " " + month_moon_rise
-
- moon_rise_time.time = data.search("td[@class = dawn-dark]//dl//dd").first.inner_html
- end
Запустим его:
- ruby lib/main.rb
- MoonRiseTime Create (0.4ms) INSERT INTO "moon_rise_times" ("time", "day") VALUES('04:53', '10 июля')
Вроде все хорошо.
Посмотрим, что сохранилось в базе с помощью небольшого скрипта lib/test_fetch_data.rb:
- # Файл с небольшим скприптом для тестирования
- # извлечения данных из таблицы moon_rise_times.
-
- # загружаем файл настройки и соединеняемся с БД в файле environment.rb
- require File.join(File.dirname(__FILE__), 'config/environment.rb')
-
- # Создаем класс MoonRiseTime, обертывающий таблицу moon_rise_times
- # Ячейки таблицы: day, time -- тип string
-
- class MoonRiseTime < ActiveRecord::Base
- end
-
- # Извлекаем все записи из БД в fetch_result
- fetch_result = MoonRiseTime.all
-
- # Выводим на экран fetch_result
- fetch_result.each do |result_item|
- puts result_item.id
- puts result_item.time
- puts result_item.day
- end
Вывод:
- $ ruby lib/test_fetch_data.rb
- MoonRiseTime Load (0.5ms) SELECT * FROM "moon_rise_times"
- 1
- 04:53
- 10 июля
Ок! Теперь, запуская каждый день нашу программу можно следить за временем восхода луны!