tsenart
2010-Feb-08 21:43 UTC
Why are double sided polymorphic relationships lacking in Rails?
http://stackoverflow.com/questions/2224994/why-are-double-sided-polymorphic-relationships-lacking-in-rails -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Mat Brown
2010-Feb-08 22:12 UTC
Re: Why are double sided polymorphic relationships lacking in Rails?
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 Mon, Feb 8, 2010 at 16:43, tsenart <tsenart-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> http://stackoverflow.com/questions/2224994/why-are-double-sided-polymorphic-relationships-lacking-in-rails > > -- > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > For more options, visit this group at http://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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
tsenart
2010-Feb-08 23:18 UTC
Re: Why are double sided polymorphic relationships lacking in Rails?
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 Feb 8, 10:12 pm, Mat Brown <m...-BtJC2HJPhyMAvxtiuMwx3w@public.gmane.org> wrote:> 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 Mon, Feb 8, 2010 at 16:43, tsenart <tsen...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >http://stackoverflow.com/questions/2224994/why-are-double-sided-polym... > > > -- > > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org 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.
tsenart
2010-Feb-09 10:40 UTC
Re: Why are double sided polymorphic relationships lacking in Rails?
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 Feb 8, 11:18 pm, tsenart <tsen...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> 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-polym... > > On Feb 8, 10:12 pm, Mat Brown <m...-BtJC2HJPhyMAvxtiuMwx3w@public.gmane.org> wrote: > > > > > 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 Mon, Feb 8, 2010 at 16:43, tsenart <tsen...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > >http://stackoverflow.com/questions/2224994/why-are-double-sided-polym... > > > > -- > > > 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-/JYPxA39Uh4Ykp1iOSErHA@public.gmane.orgm. > > > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > > > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org 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.
Mat Brown
2010-Feb-09 11:45 UTC
Re: Re: Why are double sided polymorphic relationships lacking in Rails?
On Tue, Feb 9, 2010 at 05:40, tsenart <tsenart-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> 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 = -Kh2/SeAxS2fLS4Gt8QadI4EAAcAZM0a/DiXbvYtICvo@public.gmane.org > > > On Feb 8, 11:18 pm, tsenart <tsen...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >> 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-polym... >> >> On Feb 8, 10:12 pm, Mat Brown <m...-BtJC2HJPhyMAvxtiuMwx3w@public.gmane.org> wrote: >> >> >> >> > 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 Mon, Feb 8, 2010 at 16:43, tsenart <tsen...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >> > >http://stackoverflow.com/questions/2224994/why-are-double-sided-polym... >> >> > > -- >> > > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org >> > > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > 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. -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org 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.
Marnen Laibow-Koser
2010-Feb-09 13:37 UTC
Re: Re: Why are double sided polymorphic relationships lack
Mat Brown wrote:> On Tue, Feb 9, 2010 at 05:40, tsenart <tsenart-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org >>> > > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org >> To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org >> 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-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/. -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org 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.