Шрифт
Использование ActiveRecord без Rails
Play

Использование ActiveRecord без Rails

Наш тестовый проект будет брать время восхода луны с Яндекс.Погода и сохранять ее в базу данных, используя ActiveRecord. Заодно посмотрим на работу с Nokogiri (хорошую замену hpricot).

Структура проекта

Мы будем использовать миграции, файл конфигураций database.yaml, Rakefile, базу данных sqlite (development.sqlite3), в общем, окружение приближенное к любимым рельсам.

Настройка соединения с БД и создание таблицы с помощью миграций
  1. adapter: sqlite3
  2. database: lib/db/development.sqlite3
  1. require 'rubygems'
  2. require 'active_record'
  3. require 'yaml'
  4. # Загружаем файл настройки соединения с БД
  5. dbconfig = YAML :: load(File . open(File . join (File . dirname (__FILE__) , 'database.yml' )))
  6. # Ошибки работы с БД направим в стандартный поток (консоль)
  7. ActiveRecord::Base . logger = Logger . new ( STDERR )# Simple logging utility. logger.rb -- standart lib
  8. # Соединяемся с БД
  9. ActiveRecord::Base . establish_connection ( dbconfig )
  1. class CreateMoonRiseTimes <ActiveRecord::Migration
  2. defself . up
  3. create_table :moon_rise_timesdo| t |
  4. t. string:day
  5. t. string:time
  6. end
  7. end
  8. defself . down
  9. drop_table :moon_rise_times
  10. end
  11. end
  1. require 'lib/config/environment.rb'
  2. # Документация по rake docs.rubyrake.org
  3. # namespace -- rake.rubyforge.org/classes/Rake/NameSpace.html
  4. namespace :dbdo
  5. desc "Migrate the database"
  6. task :migratedo
  7. # выполнение всех миграций из lib/db/migrate,
  8. # метод принимает параметры: migrate(migrations_path, target_version = nil)
  9. # в нашем случае
  10. # migrations_path = lib/db/migrate
  11. # target_version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
  12. # миграция запускается как rake db:migrate VERSION=номер_версии
  13. ActiveRecord::Migrator . migrate ( 'lib/db/migrate' , ENV [ "VERSION" ] ? ENV [ "VERSION" ] . to_i : nil)
  14. end
  15. end

    $ rake db:migrate VERSION = 1

Отлично. Миграция 001_create_moon_rise_times.rb создала таблицу moon_rise_times с полями day и time.

Извлечение данных и сохранение их в БД

Теперь надо найти какие-нибудь полезные данные для сохранения в базу данных. Для примера будем брать с сайта Яндекс.Погода время восхода Луны. Также можно вылавливать курсы валют, новости, значение кармы, etc.

Для начала создадим тестовый файл lib/test_search.rb ищущий нужные данные на Яндекс.Погода:

  1. # Файл с небольшим скприптом для тестирования работы nokogiri.
  2. $KCODE = "u"
  3. require 'jcode'
  4. require 'rubygems'
  5. require 'open-uri'
  6. require 'iconv'
  7. require 'nokogiri'
  8. # Загрузим html-документ
  9. source = open( "pogoda.yandex.ru/26063/details/" )
  10. # Создадим объект nokogiri из загруженного документа
  11. data = Nokogiri::HTML( source )
  12. # Извлечем все строки html-таблицы с помощью метода search и простого xpath-выражения
  13. # wiki.github.com/tenderlove/nokogiri
  14. =begin
  15. Фрагмент исходного html-файла, в котором надо найти дату восхода Луны :)
  16. <th rowspan="4"><b title="">9</b> <span>июля</span></th>
  17. =end
  18. data_html = data. search ( "th[@class = date]//b" ) . first . inner_html + " " + data. search ( "th[@class = date]//span" ) . first . inner_html
  19. puts data_html
  20. =begin
  21. Фрагмент исходного html-файла, в котором надо найти время восхода Луны в день, определенный выше :)
  22. <td rowspan="4">
  23. <dl>
  24. <dt>Восход</dt>
  25. <dd>04:52</dd>
  26. <dt>Заход</dt>
  27. <dd>23:15</dd>
  28. </dl>
  29. <img src="//i.yandex.st/weather/i/moon/07.gif" alt="Убывающая луна" title="Убывающая луна">
  30. </td>
  31. =end
  32. time_html = data. search ( "td[@class = dawn-dark]//dl//dd" ) . first . inner_html
  33. puts time_html
  1. $ ruby lib / test_search.rb
  2. 10 июля
  3. 04: 53

Ок, то, что нам нужно. Теперь надо сохранить полученные данные в БД. Для этого в ActiveRecord::Base есть метод create

Файл, выполняющий главную работу, lib/main.rb:

  1. $KCODE = "u"
  2. require 'jcode'
  3. require 'rubygems'
  4. require 'active_record'
  5. require 'yaml'
  6. require 'logger'
  7. require 'open-uri'
  8. require 'iconv'
  9. require 'nokogiri'
  10. # загружаем файл environment.rb настройки и соединение с БД
  11. requireFile . join (File . dirname (__FILE__) , 'config/environment.rb' )
  12. # Создаем класс MoonRiseTime, обертывающий таблицу moon_rise_times
  13. # Ячейки таблицы: day -- тип data, rise_times -- тип time
  14. #
  15. class MoonRiseTime <ActiveRecord::Base
  16. end
  17. MoonRiseTime. create do| moon_rise_time |
  18. # Загрузим html-документ
  19. source = open( "pogoda.yandex.ru/26063/details/" )
  20. # Создадим объект nokogiri из загруженного документа
  21. data = Nokogiri::HTML( source )
  22. # Извлечем все строки html-таблицы с помощью метода search и простого xpath-выражения
  23. # nokogiri.org/Nokogiri/XML/Node.html#method-i-inner_html
  24. # :TODO: Привести типы данных к data и time
  25. # Находим в исходном html дату
  26. data_moon_rise = data. search ( "th[@class = date]//b" ) . first . inner_html
  27. month_moon_rise = data. search ( "th[@class = date]//span" ) . first . inner_html
  28. # передаем найденные данные методам класса-обертки БД
  29. moon_rise_time. day = data_moon_rise + " " + month_moon_rise
  30. moon_rise_time. time = data. search ( "td[@class = dawn-dark]//dl//dd" ) . first . inner_html
  31. end
  1. ruby lib / main.rb
  2. MoonRiseTime Create ( 0.4ms ) INSERT INTO "moon_rise_times" ( "time" , "day" ) VALUES ( '04:53' , '10 июля' )

Вроде все хорошо.

Посмотрим, что сохранилось в базе с помощью небольшого скрипта lib/test_fetch_data.rb:

  1. # Файл с небольшим скприптом для тестирования
  2. # извлечения данных из таблицы moon_rise_times.
  3. # загружаем файл настройки и соединеняемся с БД в файле environment.rb
  4. requireFile . join (File . dirname (__FILE__) , 'config/environment.rb' )
  5. # Создаем класс MoonRiseTime, обертывающий таблицу moon_rise_times
  6. # Ячейки таблицы: day, time -- тип string
  7. class MoonRiseTime <ActiveRecord::Base
  8. end
  9. # Извлекаем все записи из БД в fetch_result
  10. fetch_result = MoonRiseTime. all
  11. # Выводим на экран fetch_result
  12. fetch_result. eachdo| result_item |
  13. puts result_item. id
  14. puts result_item. time
  15. puts result_item. day
  16. end
  1. $ ruby lib / test_fetch_data.rb
  2. MoonRiseTime Load ( 0.5ms ) SELECT * FROM "moon_rise_times"
  3. 1
  4. 04: 53
  5. 10 июля

Ок! Теперь, запуская каждый день нашу программу можно следить за временем восхода луны!

📎📎📎📎📎📎📎📎📎📎