Simple ActiveRecord question.

I've programmed in ruby for awhile, but I'm just getting into AR. I
can boil my current problem understanding it down to the following
example.

Thanks,
          Kyle

#!/usr/bin/ruby
require 'rubygems'
require 'active_record'

ActiveRecord::Base.establish_connection(:adapter => "sqlite3",
:database => "foo.db")

ActiveRecord::Schema.define() do
create_table :containers do |table|
   table.column :name, :string
end
create_table :things do |table|
   table.column :description, :string
end
end

class Container<ActiveRecord::Base
has_many :things
end

class Thing<ActiveRecord::Base
belongs_to :container
end

Container.create(:name=>"Bucket")
bucket=Container.find_by_name("Bucket")
pocket=Container.create(:name=>"Pocket")

bucket.save
pocket.save

Container.find(:all)
#this will find both containers

Thing.find(:all)
#empty, as expected

bucket.things.create(:description=>"fish")
pocket.things.create(:description=>"lint")

Thing.find(:all)
#looks good...

#but how come
pocket.things.find(:all)
#throws some huge error (below) instead of finding the things in the
pocket?

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column:
things.container_id: SELECT * FROM things WHERE (things.container_id =
2)
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/connection_adapters/abstract_adapter.rb:128:in `log'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/connection_adapters/sqlite_adapter.rb:145:in `execute'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/connection_adapters/sqlite_adapter.rb:346:in
`catch_schema_changes'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/connection_adapters/sqlite_adapter.rb:145:in `execute'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/connection_adapters/sqlite_adapter.rb:165:in
`select_all'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/base.rb:427:in `find_by_sql'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/base.rb:997:in `find_every'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/base.rb:418:in `find'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.5/lib/
active_record/associations/has_many_association.rb:91:in `find'
        from (irb):68

create_table :things do |table|
   table.column :description, :string

You need a container_id field here.

class Thing<ActiveRecord::Base
belongs_to :container

belongs_to requires a foreign key.

This is not enough: you do actually need to create the container_id column on the things table.

Fred

The "find all" is automatic. You can just magically use the pocket.things array without having to prepare it.
And if you have a Thing and you want to associate it with a Pocket, all you have to do is pocket.things << thing and AR will update thing and save it.

I was too hasty in my reply. Listen to what Greg said :slight_smile:

Fred, Greg, thanks so much. Just that simple addition made it behave
the way I thought it should :slight_smile:

create_table :things do |table|
   table.column :description, :string
   table.column :container_id, :int
end

George, now that I've got that line, it does indeed work like I'd
hoped.
Sweet.

So, now the next question, how would I find a container by it's
contents?

Container.find_by_name("Pocket")
#seems easy enough, but I can't do....
Container.find_by_thing
#OK Container.column_names only has id and name, so I can make an easy
guess why _that_ didn't work..
#but how would you get something like finding Containers by things to
work? Or is the solution really just to
#search the Thing class for container_id?

Thanks all
--Kyle