⬆️ ⬇️

Using ActiveRecord without Rails

The library for working with ActiveRecord databases can also be used outside of Rails.



Task

Our test project will take the time of the rising of the moon with Yandex. Weather and save it to the database using ActiveRecord. At the same time we will look at working with Nokogiri (a good replacement for hpricot ).



Project structure

We will use migrations, the configuration file database.yaml, Rakefile, the sqlite database (development.sqlite3), in general, an environment close to our favorite rails.



View on github .

')

image



Setting up a database connection and creating a table using migrations

For convenience, the configuration of the database connection is placed in a separate file lib / config / database.yml :

  1. adapter: sqlite3
  2. database: lib / db / development.sqlite3
And the connection to the database in lib / config / environment.rb :

  1. 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 )
  2. 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 )
  3. 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 )
  4. 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 )
  5. 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 )
  6. 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 )
  7. 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 )
  8. 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 )
  9. 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 )


Let's prepare the database migration for creating the table. For simplicity, it only has two string fields: day and time:

  1. class CreateMoonRiseTimes < ActiveRecord :: Migration
  2. def self . up
  3. create_table : moon_rise_times do | t |
  4. t. string : day
  5. t. string : time
  6. end
  7. end
  8. def self . down
  9. drop_table : moon_rise_times
  10. end
  11. end
To perform the migration, create a rake file.

  1. require 'lib / config / environment.rb'
  2. Documentation on rake docs.rubyrake.org
  3. # namespace - rake.rubyforge.org/classes/Rake/NameSpace.html
  4. namespace : db do
  5. desc "Migrate the database"
  6. task : migrate do
  7. # performing all migrations from lib / db / migrate,
  8. # method takes parameters: migrate (migrations_path, target_version = nil)
  9. # in our case
  10. # migrations_path = lib / db / migrate
  11. # target_version = ENV ["VERSION"]? ENV ["VERSION"]. To_i: nil
  12. # migration starts as rake db: migrate VERSION = version_number
  13. ActiveRecord :: Migrator . migrate ( 'lib / db / migrate' , ENV [ "VERSION" ] ? ENV [ "VERSION" ] . to_i : nil )
  14. end
  15. end




Let's migrate:

  1. $ rake db: migrate version = 1



  2. ( in / home / data / projects / ActiveRecord-without-Rails )

  3. == CreateMoonRiseTimes: migrating ============================================
  4. - create_table ( : moon_rise_times )
  5. SQL ( 1.0ms ) CREATE TABLE "moon_rise_times" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "day" varchar ( 255 ) , "time" varchar ( 255 ) )
  6. - > 0.0019s
  7. == CreateMoonRiseTimes: migrated ( 0.0020s ) ===================================
  8. SQL ( 0.1ms ) INSERT INTO schema_migrations ( version ) VALUES ( '1' )




Fine. Migration 001_create_moon_rise_times.rb created the moon_rise_times table with the day and time fields.



Extracting data and storing it in the database

Now you need to find some useful data to save to the database. For example, we will take from the site Yandeks.Pogoda time of the rising of the moon. You can also catch currency rates, news, the value of karma, etc ...



First of all, let's create a test file lib / test_search.rb that is looking for the necessary data on Yandex.Pagoda:

  1. # A file with a small script for testing the work of nokogiri.
  2. $ KCODE = "u"
  3. require 'jcode'
  4. require 'rubygems'
  5. require 'open-uri'
  6. require 'iconv'
  7. require 'nokogiri'
  8. # Download html document
  9. source = open ( "pogoda.yandex.ru/26063/details/" )
  10. # Create a nokogiri object from the loaded document
  11. data = Nokogiri :: HTML ( source )
  12. # Extract all html table rows using the search method and simple xpath expression
  13. # wiki.github.com/tenderlove/nokogiri
  14. = begin
  15. Fragment of the source html-file, in which you need to find the date of the rising of the moon :)
  16. <th class = "date" rowspan = "4"> <b title = ""> 9 </ b> <span> July </ 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. A fragment of the source html file, in which you need to find the time of the rising of the moon on the day defined above :)
  22. <td class = "dawn-dark" rowspan = "4">
  23. <dl>
  24. <dt> Sunrise </ dt>
  25. <dd> 04:52 </ dd>
  26. <dt> Sunset </ dt>
  27. <dd> 23:15 </ dd>
  28. </ dl>
  29. <img src = "// i.yandex.st/weather/i/moon/07.gif" alt = "The Waning Moon" title = "The Waning Moon">
  30. </ td>
  31. = end
  32. time_html = data. search ( "td [@class = dawn-dark] // dl // dd" ) . first . inner_html
  33. puts time_html




We get:

  1. $ ruby ​​lib / test_search.rb
  2. July 10
  3. 04: 53


Ok, what we need.

Now you need to save the data in the database. There is a create method for this in ActiveRecord :: Base



The file that does the main work, 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. # load the environment.rb file settings and connect to the database
  11. require file . join ( File . dirname ( __FILE__ ) , 'config / environment.rb' )
  12. # Create a MoonRiseTime class that wraps the moon_rise_times table
  13. # Table cells: day - data type, rise_times - time type
  14. #
  15. class MoonRiseTime < ActiveRecord :: Base
  16. end
  17. MoonRiseTime. create do | moon_rise_time |
  18. # Download html document
  19. source = open ( "pogoda.yandex.ru/26063/details/" )
  20. # Create a nokogiri object from the loaded document
  21. data = Nokogiri :: HTML ( source )
  22. # Extract all html table rows using the search method and simple xpath expression
  23. # nokogiri.org/Nokogiri/XML/Node.html#method-i-inner_html
  24. #: TODO: Cast data types to data and time
  25. # Find the original html date
  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. # pass the data found to the methods of the database wrapper class
  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


Run it:

  1. ruby lib / main.rb
  2. MoonRiseTime Create ( 0.4ms ) INSERT INTO "moon_rise_times" ( "time" , "day" ) VALUES ( '04: 53 ' , '10 July' )




It feels good.



Let's see what was saved in the database using a small script lib / test_fetch_data.rb :

  1. # File with a small script for testing
  2. # extracting data from the moon_rise_times table.
  3. # load the configuration file and connect to the database in the file environment.rb
  4. require file . join ( File . dirname ( __FILE__ ) , 'config / environment.rb' )
  5. # Create a MoonRiseTime class that wraps the moon_rise_times table
  6. # Table cells: day, time - type string
  7. class MoonRiseTime < ActiveRecord :: Base
  8. end
  9. # Extract all records from the database in fetch_result
  10. fetch_result = MoonRiseTime. all
  11. # Displaying fetch_result
  12. fetch_result. each do | result_item |
  13. puts result_item. id
  14. puts result_item. time
  15. puts result_item. day
  16. end


Conclusion:

  1. $ ruby ​​lib / test_fetch_data.rb
  2. MoonRiseTime Load ( 0.5ms ) SELECT * FROM "moon_rise_times"
  3. one
  4. 04: 53
  5. July 10


OK! Now, starting our program every day, you can follow the time of the moon rising!



Used materials

Source: https://habr.com/ru/post/98751/



All Articles