I would like to know if there''s a way to when doing STI the update_attributes, validate the attributes based on the new class type? For e.g. suppose i have: class A < ActiveRecord::Base end class B < A validates :attribute_z, :presence => true end class C < A validates :attribute_x, :presence => true validates :attribute_y, :presence => true end If i run (the way rails is implemented): b = A.find(''b-id'') b.update_attributes({ ''type'' => ''C'', :attribute_x => ''present'', :attribute_y => ''present'', :attribute_z => nil }) # will return false with errors on ''attribute_z must be present'' I''ve tried with #becomes[http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-becomes]: b = A.find(''b-id'') b = b.becomes(C) b.update_attributes({ ''type'' => ''C'', :attribute_x => ''present'', :attribute_y => ''present'', :attribute_z => nil }) # this works partially, because the validations are ok but when i look to console i get something like: UPDATE "as" SET "type" = ''c'', "attribute_z" = NULL, "attribute_y'' = ''present'', ''attribute_x'' = ''present'' WHERE "as"."type" IN (''C'') AND "as"."id" = ''b-id'' # which is terrible because it''s looking for a record of B type on the C types. i could put :if => proc { |record| record.type == ''C'' } on the validations and put the validations at A class. But it wouldn''t make sense to have the subclasses. The difference basically of B and C is only in the validation behavior. (I have many validations on both types) -- 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 To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/kD4U2PKWfhMJ. For more options, visit https://groups.google.com/groups/opt_out.
Why are you doing b = A.find("b-id") and not b = B.find("b-id") ? I think it would be better if you did b = B.find("b-id") c = b.becomes(C) try it in the console and verify that c.class is C then you should be able to do c.update_attributes(:attribute_x => ''present'', :attribute_y => ''present'') Your validations will fail if you expect Rails to make the update to an object of class B without attribute_z, which is what you''re doing here: b.update_attributes({ ''type'' => ''C'', :attribute_x => ''present'', :attribute_y => ''present'', :attribute_z => nil }) You need b to be of class C if you want your validations to pass. On Monday, January 14, 2013 1:34:29 PM UTC-5, Guilherme Reis wrote:> > I would like to know if there''s a way to when doing STI the > update_attributes, validate the attributes based on the new class type? > > For e.g. suppose i have: > > class A < ActiveRecord::Base > end > class B < A > validates :attribute_z, :presence => true > end > class C < A > validates :attribute_x, :presence => true > validates :attribute_y, :presence => true > end > > If i run (the way rails is implemented): > > b = A.find(''b-id'') > b.update_attributes({ ''type'' => ''C'', :attribute_x => ''present'', > :attribute_y => ''present'', :attribute_z => nil }) # will return false with > errors on ''attribute_z must be present'' > > I''ve tried with #becomes[ > http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-becomes > ]: > > b = A.find(''b-id'') > b = b.becomes(C) > b.update_attributes({ ''type'' => ''C'', :attribute_x => ''present'', > :attribute_y => ''present'', :attribute_z => nil }) > # this works partially, because the validations are ok but when i look > to console i get something like: > UPDATE "as" SET "type" = ''c'', "attribute_z" = NULL, "attribute_y'' = > ''present'', ''attribute_x'' = ''present'' WHERE "as"."type" IN (''C'') AND > "as"."id" = ''b-id'' > # which is terrible because it''s looking for a record of B type on the > C types. > > i could put :if => proc { |record| record.type == ''C'' } on the validations > and put the validations at A class. But it wouldn''t make sense to have the > subclasses. The difference basically of B and C is only in the validation > behavior. (I have many validations on both types) > >-- 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 To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/_c5hEbbc09EJ. For more options, visit https://groups.google.com/groups/opt_out.
On Monday, 14 January 2013 13:34:29 UTC-5, Guilherme Reis wrote:> i could put :if => proc { |record| record.type == ''C'' } on the validations > and put the validations at A class. But it wouldn''t make sense to have the > subclasses. The difference basically of B and C is only in the validation > behavior. (I have many validations on both types) >Are you positive A, B and C should really be separate classes? The fact that there are transitions that change classes makes it sound a lot like there''s really a statemachine here, not a class hierarchy... --Matt Jones -- 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 To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/b1z0OH96yBoJ. For more options, visit https://groups.google.com/groups/opt_out.