persist object to table

In looking at:

collection<<(object, …)
    Adds one or more objects to the collection by setting their foreign
keys to the collection‘s primary key.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/
ClassMethods.html#M001833

how would the the << syntax be used to add a "page" object to a
collection of, for example, Page.find(:all) ? Or, is there a better
approach?

thufir@ARRAKIS:~/projects/rss2mysql$
thufir@ARRAKIS:~/projects/rss2mysql$ ruby query_items.rb
"http://groups.google.ca/group/ruby-talk-google/browse_thread/
thread/3d4f3a54e0d72e70/20faeb97bf8abc41?show_docid=20faeb97bf8abc41"
"http://groups.google.ca/group/ruby-talk-google/browse_thread/
thread/74d7162cac57dc65/ee34c0c52546e0da?show_docid=ee34c0c52546e0da"
"http://groups.google.ca/group/ruby-talk-google/browse_thread/
thread/5d6a08246a0164a0/df3e5798fa92d304?show_docid=df3e5798fa92d304"
"http://groups.google.ca/group/ruby-talk-google/browse_thread/
thread/798fc4c39bfe900e/a80b047c807a3a23?show_docid=a80b047c807a3a23"
"http://groups.google.ca/group/ruby-talk-google/browse_thread/
thread/69e0d408a75cd3af/0721ee8e936933c6?show_docid=0721ee8e936933c6"
"http://groups.google.ca/group/ruby-talk-google/browse_thread/
thread/7d7b2cbf9661739b/cf19a7cad093ac81?show_docid=cf19a7cad093ac81"
"http://groups.google.ca/group/ruby-talk-google/browse_thread/
thread/27e1d1a3c68c9cfa/7fc7707edcc136ca?show_docid=7fc7707edcc136ca"
thufir@ARRAKIS:~/projects/rss2mysql$
thufir@ARRAKIS:~/projects/rss2mysql$ ruby scrape.rb
"http://groups.google.ca/group/ruby-talk-google/browse_thread/
thread/3d4f3a54e0d72e70/20faeb97bf8abc41?show_docid=20faeb97bf8abc41"
"*****************"
"*****************"
/var/lib/gems/1.8/gems/activerecord-2.3.4/lib/active_record/
attribute_methods.rb:255:in `method_missing': undefined method `page_id='
for #<Page id: nil, item_id: nil, page: nil> (NoMethodError)
  from scrape.rb:30
  from /usr/lib/ruby/1.8/open-uri.rb:135:in `open_uri'
  from /usr/lib/ruby/1.8/open-uri.rb:518:in `open'
  from /usr/lib/ruby/1.8/open-uri.rb:30:in `open'
  from scrape.rb:27
  from scrape.rb:22:in `each'
  from scrape.rb:22
thufir@ARRAKIS:~/projects/rss2mysql$
thufir@ARRAKIS:~/projects/rss2mysql$ nl scrape.rb
     1 require 'rubygems'
     2 require 'activerecord'
     3 require 'yaml'
     4 require 'item'
     5 require 'page'
     6 require 'open-uri'
     7 require 'pp'
       
     8 db = YAML::load(File.open('database.yml'))
       
     9 ActiveRecord::Base.establish_connection(
    10 :adapter => db["development"]["adapter"],
    11 :host => db["development"]["host"],
    12 :username => db["development"]["username"],
    13 :password => db["development"]["password"],
    14 :database => db["development"]["database"])
       
    15 items = Item.find(:all)
       
    16 items.each do |item|
    17 pp item.url
    18 pp "*****************"
    19 pp "*****************"
       
    20 open(item.url,
    21 "User-Agent" => "Mozilla/5.0 (X11; U; Linux i686; en-US;
rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15"){|f|
    22 page = Page.new
    23 page.page_id = item.id
    24 page.page = f.readlines.join #html
    25 page.save}
    26 end
thufir@ARRAKIS:~/projects/rss2mysql$
thufir@ARRAKIS:~/projects/rss2mysql$ nl item.rb
     1 require 'rubygems'
     2 require 'activerecord'
       
     3 class Item < ActiveRecord::Base
     4 has_one :page
     5 end
       
thufir@ARRAKIS:~/projects/rss2mysql$
thufir@ARRAKIS:~/projects/rss2mysql$ nl page.rb
     1 require 'rubygems'
     2 require 'activerecord'
       
     3 class Page < ActiveRecord::Base
     4 belongs_to :item
     5 validates_presence_of :item_id
     6 end
thufir@ARRAKIS:~/projects/rss2mysql$
thufir@ARRAKIS:~/projects/rss2mysql$ nl db/migrate/001_create_items.rb
     1 class CreateItems < ActiveRecord::Migration
     2 def self.up
     3 create_table :items do |t|
     4 t.column :title, :string
     5 t.column :content, :string
     6 t.column :source, :string
     7 t.column :url, :string
     8 t.column :timestamp, :timestamp
     9 t.column :keyword_id, :integer
    10 t.column :guid, :string
    11 end
    12 end
       
    13 def self.down
    14 drop_table :items
    15 end
    16 end
thufir@ARRAKIS:~/projects/rss2mysql$ nl db/migrate/002_create_pages.rb
     1 class CreatePages < ActiveRecord::Migration
     2 def self.up
     3 create_table :pages do |t|
     4 t.references :item
     5 t.column :page, :text
     6 end
     7 end
       
     8 def self.down
     9 drop_table :pages
    10 end
    11 end
thufir@ARRAKIS:~/projects/rss2mysql$
thufir@ARRAKIS:~/projects/rss2mysql$

thanks, Thufir

Hello Thufir:

I'm not quite sure if I understand you correctly.The collection in the
documentation refers to a has_many association on the parent object
e.g. category = Category.find(1); category.pages << Page.new(:title =>
"My Title").

Could you please clarify what you wanted to do?

Cheers,
Nicholas

Speaking generally:

A has a zero or one relation with B. B always belongs to an existing
A. (Since this is ActiveRecord, A and B are both classes and tables;
and, no not using a full rails environment, just the AR gem.)

In some_insert_script.rb, a connection to the database is
established. I can query for A, or I can query for B successfully. I
don't know the syntax to check whether A has a B, and, if not, create
a B and populate the field(s) for B.

Hopefully, that makes more sense!

-Thufir

Hello Thufir:

If I understand you correctly then all you would need to do is check
the relationship is nil? From you example:

A = Item
B = Page

item = Item.find(1)
item.create_page(:title => "My Title") if item.page.nil? # or
alternative use item.build_page

Am I missing something?

Cheers,
Nicholas

or rather:

item.create_page(:title => "My Title") unless item.page

don't need to explicitly test for nil with an "if" statement.

Cheers,
Nicholas

Perfect:

thufir@ARRAKIS:~/projects/rss2mysql$
thufir@ARRAKIS:~/projects/rss2mysql$ nl scrape.rb
     1 require 'rubygems'
     2 require 'activerecord'
     3 require 'yaml'
     4 require 'item'
     5 require 'page'
     6 require 'open-uri'
     7 require 'pp'

     8 db = YAML::load(File.open('database.yml'))

     9 ActiveRecord::Base.establish_connection(
    10 :adapter => db["development"]["adapter"],
    11 :host => db["development"]["host"],
    12 :username => db["development"]["username"],
    13 :password => db["development"]["password"],
    14 :database => db["development"]["database"])

    15 items = Item.find(:all)

    16 items.each do |item|
    17 pp "*****************"
    18 pp "*****************"

    19 open(item.url,
    20 "User-Agent" => "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:
1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15"){|f|
    21 html_string = f.readlines.join
    22 item.create_page(:page => html_string) unless item.page
    23 item.save
    24 pp item.id
    25 }
    26 end
thufir@ARRAKIS:~/projects/rss2mysql$

thanks,

Thufir