I have a custom class, but I want to be able to pass it to Arel and let it resolve its queryable part.
module Custom class Item attr_accessor :name def initialize(name) self.name = name end end end custom_item = Custom::Item.new("Bill") User.where(:name => custom_item)
is there anything I can define in custom_item, so it would understand that Arel wants name from it?
Currently I workaround with:
module Arel module Visitors class ToSql def visit_Custom_Item o "'#{o.name}'" end end end end
I think it's not possible now. Let's try to figure out why.
When you try to pass your custom object to the where
method User.where(:name => custom_item)
Arel try to call visit_YOUR_CLASS_NAME
method (https://github.com/rails/arel/blob/master/lib/arel/visitors/visitor.rb#L15) but it fails. Then Arel try to call visit_
+object.class.ancestors.find {|klass| respond_to?(DISPATCH[klass], true)}
but it fails again because:
irb(main):001:0> class Foo
irb(main):002:1> end
=> nil
irb(main):003:0> foo = Foo.new
=> #<Foo:0x261edc0>
irb(main):004:0> foo.class.ancestors.map {|klass| p klass}
Foo
Object
Kernel
BasicObject
=> [Foo, Object, Kernel, BasicObject]
and Arel doesn't have any of this names in this list https://github.com/rails/arel/blob/master/lib/arel/visitors/to_sql.rb#L394:
alias :visit_ActiveSupport_Multibyte_Chars :quoted
alias :visit_ActiveSupport_StringInquirer :quoted
alias :visit_BigDecimal :quoted
alias :visit_Class :quoted
alias :visit_Date :quoted
alias :visit_DateTime :quoted
alias :visit_FalseClass :quoted
alias :visit_Float :quoted
alias :visit_Hash :quoted
alias :visit_NilClass :quoted
alias :visit_String :quoted
alias :visit_Symbol :quoted
alias :visit_Time :quoted
alias :visit_TrueClass :quoted
Actually, I don't think it's a very useful feature but I've asked Aaron Patterson about this and if he'll like it I'll try to implement it.
I was able to circumvent this problem by defining to_s
method for my class
class CustomItem
def to_s
custom_id
end
end
And tricking Arel Visitor to treat my class as Fixnum
Arel::Visitors::Visitor::DISPATCH[CustomItem] = 'visit_Fixnum'
Worked with Rails 3.2.13.
For string-like value you should probably mimick String
and use visit_String
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With