Peter Brown
2012-Jul-15 14:01 UTC
Adding new ARel visitors to resolve TypeError: Cannot visit ClassName
Is there an approved way to add or register a new ARel visitor without adding it to the ARel source? Looking at the some of the source code<https://github.com/rails/arel/blob/master/lib/arel/visitors/to_sql.rb#L434-466> it appears that new visitors are just hard coded as a new methods or aliases. The reason I''m asking is because I get "TypeError: Cannot visit ClassName" when I override reader methods with some sort of composed object (similar to Active Record''s composed_of) and use that attribute in a uniqueness validation. Take the following for example: class Cat < ActiveRecord::Base validates :name, :uniqueness => { :scope => [:breed] } def breed CatBreed.new(super) end end class CatBreed def initialize(breed) @breed = breed end def to_s @breed end end The above code will raise "TypeError: Cannot visit CatBreed" when I try to create a new cat unless I add a visitor method to Arel::Visitors::ToSql called visit_CatBreed: class Arel::Visitors::ToSql def visit_CatBreed(value) quoted(value.to_s) end end I''m hoping there is a better way to deal with this problem, either with a less hacky ARel approach or something different all together. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-core/-/rKzxKCppeZcJ. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Aaron Patterson
2012-Jul-15 17:50 UTC
Re: Adding new ARel visitors to resolve TypeError: Cannot visit ClassName
On Sun, Jul 15, 2012 at 07:01:38AM -0700, Peter Brown wrote:> Is there an approved way to add or register a new ARel visitor without > adding it to the ARel source? Looking at the some of the source code<https://github.com/rails/arel/blob/master/lib/arel/visitors/to_sql.rb#L434-466> it > appears that new visitors are just hard coded as a new methods or aliases. > > The reason I''m asking is because I get "TypeError: Cannot visit ClassName" > when I override reader methods with some sort of composed object (similar > to Active Record''s composed_of) and use that attribute in a uniqueness > validation. > > Take the following for example: > > class Cat < ActiveRecord::Base > validates :name, :uniqueness => { :scope => [:breed] } > > def breed > CatBreed.new(super) > end > end > > class CatBreed > def initialize(breed) > @breed = breed > end > > def to_s > @breed > end > end > > The above code will raise "TypeError: Cannot visit CatBreed" when I try to > create a new cat unless I add a visitor method to Arel::Visitors::ToSql > called visit_CatBreed: > > class Arel::Visitors::ToSql > def visit_CatBreed(value) > quoted(value.to_s) > end > endDoing this is fine for now. The way the AST is translated to SQL won''t change, so this will probably not break in the future.> I''m hoping there is a better way to deal with this problem, either with a > less hacky ARel approach or something different all together.It seems like we should be using the underlying database value (the attribute value rather than the return value of the method call) for the unique constraint. I think this might be a bug. Jon, wdyt? -- Aaron Patterson http://tenderlovemaking.com/
Peter Brown
2012-Jul-15 19:43 UTC
Re: Adding new ARel visitors to resolve TypeError: Cannot visit ClassName
Aaron, Thanks for the reply. I played around with it a little and it seems like changing how the scope_value is retrieved in ActiveRecordmodule::Validationsclass::UniquenessValidator<https://github.com/rails/rails/blob/master/activerecord/lib/active_record/validations/uniqueness.rb#L29-32>would fix the issue (though I''m not sure what sort of repercussions this would have elsewhere) scope_value = record.send(scope_item) to either of these record[scope_item] record.read_attribute(scope_item) On Sunday, July 15, 2012 1:50:01 PM UTC-4, Aaron Patterson wrote:> > On Sun, Jul 15, 2012 at 07:01:38AM -0700, Peter Brown wrote: > > Is there an approved way to add or register a new ARel visitor without > > adding it to the ARel source? Looking at the some of the source code< > https://github.com/rails/arel/blob/master/lib/arel/visitors/to_sql.rb#L434-466> > it > > appears that new visitors are just hard coded as a new methods or > aliases. > > > > The reason I''m asking is because I get "TypeError: Cannot visit > ClassName" > > when I override reader methods with some sort of composed object > (similar > > to Active Record''s composed_of) and use that attribute in a uniqueness > > validation. > > > > Take the following for example: > > > > class Cat < ActiveRecord::Base > > validates :name, :uniqueness => { :scope => [:breed] } > > > > def breed > > CatBreed.new(super) > > end > > end > > > > class CatBreed > > def initialize(breed) > > @breed = breed > > end > > > > def to_s > > @breed > > end > > end > > > > The above code will raise "TypeError: Cannot visit CatBreed" when I try > to > > create a new cat unless I add a visitor method to Arel::Visitors::ToSql > > called visit_CatBreed: > > > > class Arel::Visitors::ToSql > > def visit_CatBreed(value) > > quoted(value.to_s) > > end > > end > > Doing this is fine for now. The way the AST is translated to SQL won''t > change, so this will probably not break in the future. > > > I''m hoping there is a better way to deal with this problem, either with > a > > less hacky ARel approach or something different all together. > > It seems like we should be using the underlying database value (the > attribute value rather than the return value of the method call) for the > unique constraint. I think this might be a bug. Jon, wdyt? > > -- > Aaron Patterson > http://tenderlovemaking.com/ >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-core/-/aqW06gxjXEsJ. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Jon Leighton
2012-Jul-16 19:36 UTC
Re: Adding new ARel visitors to resolve TypeError: Cannot visit ClassName
>> I''m hoping there is a better way to deal with this problem, either with a >> less hacky ARel approach or something different all together. > > It seems like we should be using the underlying database value (the > attribute value rather than the return value of the method call) for the > unique constraint. I think this might be a bug. Jon, wdyt?Yes, I agree. Who wants to create a patch? :) -- http://jonathanleighton.com/ -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Peter Brown
2012-Jul-17 00:49 UTC
Re: Adding new ARel visitors to resolve TypeError: Cannot visit ClassName
Me :) https://github.com/rails/rails/pull/7072 On Monday, July 16, 2012 3:36:39 PM UTC-4, Jon Leighton wrote:> > >> I''m hoping there is a better way to deal with this problem, either with > a > >> less hacky ARel approach or something different all together. > > > > It seems like we should be using the underlying database value (the > > attribute value rather than the return value of the method call) for the > > unique constraint. I think this might be a bug. Jon, wdyt? > > Yes, I agree. Who wants to create a patch? :) > > -- > http://jonathanleighton.com/ > > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-core/-/sY4OrKfqp94J. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.