http://stackoverflow.com/questions/2224994/why-are-double-sided-polymorphic-relationships-lacking-in-rails
on 2010-02-08 23:11
on 2010-02-08 23:13
Inverse associations will be standard in Rails 2.3.6. For the impatient, here's a backport: http://github.com/oggy/inverse_of Mat
on 2010-02-09 09:57
Very cool! Thanks for the answer. But inverse associations are only a component of those double sided polymorphic associations. At the present you can only make one sided associations. Table talking it means the following: Single sided polymorphic: ----------------------------------------------- | origin_id | destination_id | destination_type | ----------------------------------------------- Double sided polymorphic: ------------------------------------------------------------- | origin_id | origin_type | destination_id | destination_type | ------------------------------------------------------------- This way there's only on table to track all these relations. It allows every model to be associated with every other model as many times as needed. For a better explanation I wrote something on Stackoverflow -> Here is the link again: http://stackoverflow.com/questions/2224994/why-are-double-sided-polymorphic-relationships-lacking-in-rails&usg=AFQjCNEK8nv15YTOV3IYYh-2od_6Ng4Eug
on 2010-02-09 11:42
ActiveRecord supports one-to-many polymorphic associations but not
many-to-many polymorphic associations. Thats what I wanted.
I emulate that behavior like this:
We have three models: - Article, Asset and Relationship
class Article < PolyRecord
habtm_polymorphs [:assets]
end
class Asset < PolyRecord
habtm_polymorphs [:articles]
end
class Relationship < ActiveRecord::Base
belongs_to :origin, :polymorphic => true
belongs_to :destination, :polymorphic => true
after_create :create_reverse_relationship
private
def create_reverse_relationship
rev = Relationship.new :origin => self.destination, :destination
=> self.origin
rev.save(false)
true
end
end
class PolyRecord < ActiveRecord::Base
self.abstract_class = true
def self.habtm_polymorphs(associations, options={})
associations = [associations].flatten
options[:polymorphic_join_table] ||= 'relationships'
options[:polymorphic_from] ||= 'origin'
options[:polymorphic_to] ||= 'destination'
pjoin = options[:polymorphic_join_table]
pto = options[:polymorphic_to]
pfrom = options[:polymorphic_from]
has_many pjoin, :as => pto
has_many pjoin, :as => pfrom
associations.each do |assoc|
has_many assoc, :through => pjoin, :source => pto, :source_type
=> assoc.to_s.singularize.camelize
end
after_destroy do |obj|
Relationship.delete_all({
:destination_id => obj.id,
:destination_type => obj.class.to_s
})
Relationship.delete_all({
:origin_id => obj.id,
:origin_type => obj.class.to_s
})
end
associations.each do |assoc|
define_method "#{assoc}=".to_sym do |args|
eval "self.#{assoc}.clear"
args = [args].flatten
Relationship.delete_all({
:origin_type => assoc.to_s.singularize.capitalize,
:destination_id => self.id,
:destination_type => self.class.to_s })
Relationship.destroy_all({
:origin_id => self.id,
:origin_type => self.class.to_s,
:destination_type => assoc.to_s.singularize.camelize })
eval "self.#{assoc} << args" unless args.empty?
end
end
end
end
Then you can use it like this:
@asset = Asset.new
@asset.articles = Article.first
@asset.articles = Article.all
@asset.articles << Article.new
@article.assets = @asset.articles.first.assets.last
on 2010-02-09 12:47
On Tue, Feb 9, 2010 at 05:40, tsenart <tsenart@gmail.com> wrote: > habtm_polymorphs [:articles] > rev = Relationship.new :origin => self.destination, :destination > def self.habtm_polymorphs(associations, options={}) > has_many pjoin, :as => pfrom > }) > args = [args].flatten > > @asset.articles = Article.first >> >> This way there's only on table to track all these relations. It allows >> > impatient, here's a backport: >> > > To post to this group, send email to rubyonrails-talk@googlegroups.com. >> > > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. >> > > For more options, visit this group athttp://groups.google.com/group/rubyonrails-talk?hl=en. > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk@googlegroups.com. > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en. > > Ah, I see what you're getting at. When I've had to do that, I use full-blown model for the join table, and then a has_many :through to define the relationship between the endpoints. It's not a perfect solution but probably the best that's possible in AR.
on 2010-02-09 14:37
Mat Brown wrote: > On Tue, Feb 9, 2010 at 05:40, tsenart <tsenart@gmail.com> wrote: >> �habtm_polymorphs [:articles] >> � �rev = Relationship.new :origin => self.destination, :destination >> �def self.habtm_polymorphs(associations, options={}) >> � �has_many pjoin, :as => pfrom >> � � �}) >> � � � �args = [args].flatten >> >> @asset.articles = Article.first >>> >>> This way there's only on table to track all these relations. It allows >>> > impatient, here's a backport: >>> > > To post to this group, send email to rubyonrails-talk@googlegroups.com. >>> > > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. >>> > > For more options, visit this group athttp://groups.google.com/group/rubyonrails-talk?hl=en. >> >> -- >> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. >> To post to this group, send email to rubyonrails-talk@googlegroups.com. >> To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. >> For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en. >> >> > > Ah, I see what you're getting at. > > When I've had to do that, I use full-blown model for the join table, > and then a has_many :through to define the relationship between the > endpoints. It's not a perfect solution but probably the best that's > possible in AR. Would has_many_polymorphs help? Best, -- Marnen Laibow-Koser http://www.marnen.org marnen@marnen.org
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.