I have been working on a polymorphic STI schema where the inheriting classes have associations: class Asset < ActiveRecord::Base end class Sound < Asset belongs_to :user, :polymorphic => true end class User < ActiveRecord::Base has_many :sounds end The Asset class contains a ''type'' attribute which is getting properly populated with the inheriting class''s name, so that''s fine, but I was getting an error that there was no ''user_type'': undefined method `user_type'' for #<Sound:0x4cf3740> OK, so I added ''user_type'' to the Asset model and I can get past that error (which was only raised upon a :destroy for the object). However, now that I''ve added it, the user_type is not being populated when new objects are created/saved. Am I missing something? -eric
On Sep 16, 1:52 pm, Eric <ericgh...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I have been working on a polymorphic STI schema where the inheriting > classes have associations: > > class Asset < ActiveRecord::Base > end > > class Sound < Asset > belongs_to :user, :polymorphic => true > end > > class User < ActiveRecord::Base > has_many :sounds > end > > The Asset class contains a ''type'' attribute which is getting properly > populated with the inheriting class''s name, so that''s fine, but I was > getting an error that there was no ''user_type'': > > undefined method `user_type'' for #<Sound:0x4cf3740> > > OK, so I added ''user_type'' to the Asset model and I can get past that > error (which was only raised upon a :destroy for the object). However, > now that I''ve added it, the user_type is not being populated when new > objects are created/saved. Am I missing something?The :polymorphic and the user_type field aren''t necessary - polymorphic associations are used when you''ve got objects from multiple tables that all might be associated to a record, eg: class Foo < AR::Base belongs_to :things, :polymorphic => true end class ThingA < AR::Base has_many :foos, :as => :thing end class ThingB < AR::Base has_many :foos, :as => :thing end Note that ThingA and ThingB are in seperate tables - if they were related via STI the :polymorphic wouldn''t be needed. --Matt Jones
On Sep 17, 8:44 am, Matt Jones <al2o...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Sep 16, 1:52 pm, Eric <ericgh...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > I have been working on a polymorphic STI schema where the inheriting > > classes have associations: > > > class Asset < ActiveRecord::Base > > end > > > class Sound < Asset > > belongs_to :user, :polymorphic => true > > end > > > class User < ActiveRecord::Base > > has_many :sounds > > end > > > The Asset class contains a ''type'' attribute which is getting properly > > populated with the inheriting class''s name, so that''s fine, but I was > > getting an error that there was no ''user_type'': > > > undefined method `user_type'' for #<Sound:0x4cf3740> > > > OK, so I added ''user_type'' to the Asset model and I can get past that > > error (which was only raised upon a :destroy for the object). However, > > now that I''ve added it, the user_type is not being populated when new > > objects are created/saved. Am I missing something? > > The :polymorphic and the user_type field aren''t necessary - > polymorphic associations are used when you''ve got objects from > multiple tables that all might be associated to a record, eg: > > class Foo < AR::Base > belongs_to :things, :polymorphic => true > end > > class ThingA < AR::Base > has_many :foos, :as => :thing > end > > class ThingB < AR::Base > has_many :foos, :as => :thing > end > > Note that ThingA and ThingB are in seperate tables - if they were > related via STI the :polymorphic wouldn''t be needed.Thanks for the reply, and I did leave a part out of my schema. There will be other models inheriting from Asset, such that ultimately there will be (at least): class Asset < ActiveRecord::Base end class Sound < Asset belongs_to :user, :polymorphic => true end class Video < Asset belongs_to :user, :polymorphic => true end class Image < Asset belongs_to :user, :polymorphic => true end class User < ActiveRecord::Base has_many [:sounds,:videos,:images] end The idea will be to have @user.videos, @user.images, etc., so the STI will handle the media types, and the polymorphism is used for User''s relationship to each. However, currently user_id is not being saved through the association, and even if I manually set user_id in Asset (and user_type, just for fun), Video.first.user comes up nil. So, STI is working as expected, but the association is broken in some way that leads me to wonder whether Asset needs some connection with User (unlikely, given the docs and commentary I''ve been able to find), or whether the STI classes need some more connections to the base class in order for User to pass through the STI. -eric
On Sep 17, 11:10 am, Eric <ericgh...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Sep 17, 8:44 am, Matt Jones <al2o...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > On Sep 16, 1:52 pm, Eric <ericgh...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > I have been working on a polymorphic STI schema where the inheriting > > > classes have associations: > > > > class Asset < ActiveRecord::Base > > > end > > > > class Sound < Asset > > > belongs_to :user, :polymorphic => true > > > end > > > > class User < ActiveRecord::Base > > > has_many :sounds > > > end > > > > The Asset class contains a ''type'' attribute which is getting properly > > > populated with the inheriting class''s name, so that''s fine, but I was > > > getting an error that there was no ''user_type'': > > > > undefined method `user_type'' for #<Sound:0x4cf3740> > > > > OK, so I added ''user_type'' to the Asset model and I can get past that > > > error (which was only raised upon a :destroy for the object). However, > > > now that I''ve added it, the user_type is not being populated when new > > > objects are created/saved. Am I missing something? > > > The :polymorphic and the user_type field aren''t necessary - > > polymorphic associations are used when you''ve got objects from > > multiple tables that all might be associated to a record, eg: > > > class Foo < AR::Base > > belongs_to :things, :polymorphic => true > > end > > > class ThingA < AR::Base > > has_many :foos, :as => :thing > > end > > > class ThingB < AR::Base > > has_many :foos, :as => :thing > > end > > > Note that ThingA and ThingB are in seperate tables - if they were > > related via STI the :polymorphic wouldn''t be needed. > > Thanks for the reply, and I did leave a part out of my schema. There > will be other models inheriting from Asset, such that ultimately there > will be (at least): > > class Asset < ActiveRecord::Base > end > > class Sound < Asset > belongs_to :user, :polymorphic => true > end > > class Video < Asset > belongs_to :user, :polymorphic => true > end > > class Image < Asset > belongs_to :user, :polymorphic => true > end > > class User < ActiveRecord::Base > has_many [:sounds,:videos,:images] > end > > The idea will be to have @user.videos, @user.images, etc., so the STI > will handle the media types, and the polymorphism is used for User''s > relationship to each. However, currently user_id is not being saved > through the association, and even if I manually set user_id in Asset > (and user_type, just for fun), Video.first.user comes up nil. So, STI > is working as expected, but the association is broken in some way that > leads me to wonder whether Asset needs some connection with User > (unlikely, given the docs and commentary I''ve been able to find), or > whether the STI classes need some more connections to the base class > in order for User to pass through the STI. > > -ericOK, so setting user_type to "User" manually in the base class does seem to work. I''m not sure why I couldn''t find the user from (e.g.) @sound before, but that''s water under the bridge now. The problem now seems to be that even though Sound[,Video,etc.] are polymorphic to User, the user_type attribute in the base class is not getting set when saved through an inheriting class. Why could this be? Is there some kind of accepts_nested_attributes_for catch that I''m not accounting for? Alternatively, is there a way to see the mechanism by which the type field is set? More explicit logging, perhaps? -eric
On Sep 17, 2:10 pm, Eric <ericgh...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Thanks for the reply, and I did leave a part out of my schema. There > will be other models inheriting from Asset, such that ultimately there > will be (at least): > > class Asset < ActiveRecord::Base > end > > class Sound < Asset > belongs_to :user, :polymorphic => true > end > > class Video < Asset > belongs_to :user, :polymorphic => true > end > > class Image < Asset > belongs_to :user, :polymorphic => true > end > > class User < ActiveRecord::Base > has_many [:sounds,:videos,:images] > end > > The idea will be to have @user.videos, @user.images, etc., so the STI > will handle the media types, and the polymorphism is used for User''s > relationship to each. However, currently user_id is not being saved > through the association, and even if I manually set user_id in Asset > (and user_type, just for fun), Video.first.user comes up nil. So, STI > is working as expected, but the association is broken in some way that > leads me to wonder whether Asset needs some connection with User > (unlikely, given the docs and commentary I''ve been able to find), or > whether the STI classes need some more connections to the base class > in order for User to pass through the STI. >Not sure what the issue you''re experiencing is - I''ll have to mock some things up and try it. But I''ll reiterate that the :polymorphic is not needed on those belongs_to declarations. The record that they point to (a User) is always in the same table. You wouldn''t even need it going the other way (some kind of User belongs_to :media, for instance). Oh, and that has_many isn''t (AFAIK) valid syntax... --Matt Jones
As my knowledge, it should be : class Asset < ActiveRecord::Base belongs_to :userable, :polymorphic => true def userable_type=(sType) super(sType.to_s.classify.constantize.base_class.to_s) end end class Sound < Asset end class User < ActiveRecord::Base has_many :assets , :as=>:userable end and in your assets table you must have 2 columns : userable_id and userable_type best regards On Sep 19, 1:12 am, Matt Jones <al2o...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Sep 17, 2:10 pm, Eric <ericgh...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > Thanks for the reply, and I did leave a part out of my schema. There > > will be other models inheriting from Asset, such that ultimately there > > will be (at least): > > > class Asset < ActiveRecord::Base > > end > > > class Sound < Asset > > belongs_to :user, :polymorphic => true > > end > > > class Video < Asset > > belongs_to :user, :polymorphic => true > > end > > > class Image < Asset > > belongs_to :user, :polymorphic => true > > end > > > class User < ActiveRecord::Base > > has_many [:sounds,:videos,:images] > > end > > > The idea will be to have @user.videos, @user.images, etc., so the STI > > will handle the media types, and the polymorphism is used for User''s > > relationship to each. However, currently user_id is not being saved > > through the association, and even if I manually set user_id in Asset > > (and user_type, just for fun), Video.first.user comes up nil. So, STI > > is working as expected, but the association is broken in some way that > > leads me to wonder whether Asset needs some connection with User > > (unlikely, given the docs and commentary I''ve been able to find), or > > whether the STI classes need some more connections to the base class > > in order for User to pass through the STI. > > Not sure what the issue you''re experiencing is - I''ll have to mock > some things up and try it. But I''ll reiterate that the :polymorphic is > not needed on those belongs_to declarations. The record that they > point to (a User) is always in the same table. You wouldn''t even need > it going the other way (some kind of User belongs_to :media, for > instance). > > Oh, and that has_many isn''t (AFAIK) valid syntax... > > --Matt Jones
On Sep 19, 7:33 am, robdoan <quydoant...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> As my knowledge, it should be : >[snip]> def userable_type=(sType) > super(sType.to_s.classify.constantize.base_class.to_s) > end > end >Um, no. If you''re needing to do this, you''ve done something seriously wrong. This is already supported by :polymorphic => true. Also note that your "solution" here will fail if the class associated to the table (Asset in this case) is more than one level above the class being stored (ie Asset > Sound > Mp3 will try to find records in a ''sounds'' table => FAIL) --Matt Jones
no, it still work event your class is inherited more than one level On Sep 21, 1:08 am, Matt Jones <al2o...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Sep 19, 7:33 am, robdoan <quydoant...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > As my knowledge, it should be : > > [snip] > > def userable_type=(sType) > > super(sType.to_s.classify.constantize.base_class.to_s) > > end > > end > > Um, no. If you''re needing to do this, you''ve done something seriously > wrong. This is already supported by :polymorphic => true. Also note > that your "solution" here will fail if the class associated to the > table (Asset in this case) is more than one level above the class > being stored (ie Asset > Sound > Mp3 will try to find records in a > ''sounds'' table => FAIL) > > --Matt Jones