Assigning objects

I’m a Ruby N. (hey that rhymes!) and I suspect I haven’t understood
the syntax properly.
I’m trying to assign one ActiveRecord object to the field of another and
I think this should work:

org = Organisation.new
=> #<Organisation:0xb7652dd8 @new_record=true,
@attributes={“fax_number”=>nil, “postal_address”=>nil, “name”=>nil,
“org_structure_id”=>0, “location_address”=>nil, “tin”=>nil,
“phone_number”=>nil, “contact”=>nil, “email_address”=>nil}>

org.name = “Aces High Inc.”
=> “Aces High Inc.”

person = NaturalPerson.new
=> #<NaturalPerson:0xb764997c @new_record=true,
@attributes={“postal_address”=>nil, “fax_number”=>nil, “name”=>nil,
“dob”=>nil, “phone_number”=>nil, “visa”=>nil, “mobile_number”=>nil,
“email_address”=>nil, “nationality”=>nil}>

person.name = “Fred Flinstone”
=> “Fred Flinstone”

org.contact << person
NoMethodError: You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occured while evaluating nil.<<
from (irb):13

My Organisation model looks like this:

class Organisation < ActiveRecord::Base
belongs_to :org_structure
belongs_to :natural_person, {:foreign_key => “contact”}
has_many :natural_people, :through => :associates
validates_associated :org_structure
end

So by my understanding that second “belongs_to” call is supposed to
enable me to make the assignment that’s failing. It’s 1 o’clock in the
morning, maybe this will make sense after a sleep…

Hi –

On Thu, 14 Dec 2006, Michael H. wrote:

I’m a Ruby N. (hey that rhymes!)

That’s usually called a “nuby” :slight_smile:

and I suspect I haven’t understood the syntax properly.
I’m trying to assign one ActiveRecord object to the field of another and
I think this should work:

org = Organisation.new
org.name = “Aces High Inc.”
person = NaturalPerson.new
person.name = “Fred Flinstone”
org.contact << person
NoMethodError: You have a nil object when you didn’t expect it!

The << is only for collections, where you’re adding one to many (like
library.books << some_book). Here there’s only one of everything.

The method you call on the object, for an association, is always the
name of the association itself. You have no association called
“contact”:

My Organisation model looks like this:

class Organisation < ActiveRecord::Base
belongs_to :org_structure
belongs_to :natural_person, {:foreign_key => “contact”}
has_many :natural_people, :through => :associates
validates_associated :org_structure
end

Either you need to set the value like this:

org.natural_person = person

or, if you want to use org.contact, you need to change the
natural_person association to this:

belongs_to :contact,
:class_name => “NaturalPerson”,
:foreign_key => “contact_id”

and make any corresponding changes in natural_person.rb

David


Q. What’s a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Thank you Jason and David for your replies!

David said:

The << is only for collections, where you’re adding one to many (like
library.books << some_book). Here there’s only one of everything.

Brilliant! That’s a bit of info that I didn’t have.

has_many :natural_people, :through => :associates
validates_associated :org_structure
end

OK, this sentence had to make me re-evaluate my understanding of what
was going on!

I have defined a field “contact” in my table “organisations” and I was
expecting this statement do set up the association:

belongs_to :natural_person, :foreign_key => "contact"

In my mind I was saying “Right, it’s going to derive the class name from
the association, so it will correctly get the NaturalPerson class and
I’ve stated that the foreign key is called ‘contact’ so I can access
that class through the ‘contact’ member”.

OK, so that is wrong!

if you want to use org.contact, you need to change the
natural_person association to this:

belongs_to :contact,
:class_name => “NaturalPerson”,
:foreign_key => “contact_id”

and make any corresponding changes in natural_person.rb

I do want to use org.contact, so I changed my model as per what you’ve
put above:

class Organisation < ActiveRecord::Base
  belongs_to :contact, {:class_name => "NaturalPerson", :foreign_key
=> "contact"}

The thing that hasn’t clicked in my mind yet is that the association and
foreign key have the same value - they are redundant (in my particular
case). So I thought “Maybe the association name is the same as the field
name by convention, but I could actually use any arbitrary name”. So I
tried this:

class Organisation < ActiveRecord::Base
  belongs_to :foo, {:class_name => "NaturalPerson", :foreign_key =>
"contact"}

So if my presumption is correct, I can update the “contact” field in the
database by playing with the “foo” association in the ActiveRecord.

 >> org = Organisation.new
 >> org.name = "Wacky Widgets Pty Ltd"
 >> person = NaturalPerson.new
 >> person.name = "Barney Rubble"
 >> org.foo = person
 >> org.save
 >> puts org.foo.name
Barney Rubble
 >> puts org.contact.name
NoMethodError: undefined method `name' for 2:Fixnum
        from (irb):14

By George I think I’ve got it!

“Contact” is just a plain old integer, as I defined it in the
ActiveRecord::Migration.

If I used “belongs_to” with the association name “contact” it will
override the integer “contact” and add all the funkiness I’m looking
for.

Thank you, thank you, thank you!