Recommendations for multiple associations with one class in Rails?

I think my question is best described as an example. Let's say I have a simple model called “Thing”, and it has several attributes that are simple data types. Sort of...

Thing
   - foo:string
   - goo:string
   - bar:int

This is not difficult. The db table will contain three columns with these three attributes, and I can access them with something like @ thing.foo or @ thing.bar.

But the problem I'm trying to solve is what happens when "foo" or "goo" can no longer be contained in a simple data type? Suppose foo and goo represent the same type of object. That is, they are both instances of "Whazit" with only different data. So now, Thing might look like this ...

Thing
  - bar:int

"Whazit", :

Whazit
  - content:string
  - value:int
  - thing_id:int

. . @thing, 2 Whazit ( "-" , Thing 2 Whazits)? , , Whazit foo goo. , @thing.foo , .

"name" Whazit, Whatzits, @thing, Whazit, . , .

?

+5
2

. -, belongs_to/has_one:

things
  - bar:int
  - foo_id:int
  - goo_id:int

whazits
  - content:string
  - value:int

class Thing < ActiveRecord::Base
  belongs_to :foo, :class_name => "whazit"
  belongs_to :goo, :class_name => "whazit"
end

class Whazit < ActiveRecord::Base
  has_one :foo_owner, class_name => "thing", foreign_key => "foo_id"
  has_one :goo_owner, class_name => "thing", foreign_key => "goo_id"

  # Perhaps some before save logic to make sure that either foo_owner
  # or goo_owner are non-nil, but not both.
end

, , .., . : Foo Goo, whazits , .

things
  - bar:int

whazits
  - content:string
  - value:int
  - thing_id:int
  - type:string

class Thing < ActiveRecord::Base
  belongs_to :foo
  belongs_to :goo
end

class Whazit < ActiveRecord::Base
  # .. whatever methods they have in common ..
end

class Foo < Whazit
  has_one :thing
end

class Goo < Whazit
  has_one :thing
end

, @thing.foo @thing.goo. , :

@thing.foo = Whazit.new

, :

@thing.foo = Foo.new

STI , . , @object.class, @object.base_class. , .

+8

"" :

class Thing < ActiveRecord::Base
  has_one :foo, :class_name => "whazit", :conditions => { :name => "foo" }
  has_one :goo, :class_name => "whazit", :conditions => { :name => "goo" }
end

, STI, , .

, , , , whazit. :

def foo=(assoc)
  assos.name = 'foo'
  super(assoc)
end
+2

All Articles