2011-06-15 56 views
5

我有一個自定義類,但我希望能夠將它傳遞給Arel並讓它解析其可查詢部分。Rails3 Arel訪問自定義類

 
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) 

有什麼我可以在custom_item中定義的,所以它會明白Arel想要它的名字?

目前我解決方法有:

 
module Arel 
    module Visitors 
    class ToSql 
     def visit_Custom_Item o 
     "'#{o.name}'" 
     end 
    end 
    end 
end 

回答

5

我認爲它現在是不可能的。讓我們試圖找出原因。

當您嘗試自定義對象傳遞給where方法User.where(:name => custom_item)阿雷爾嘗試調用visit_YOUR_CLASS_NAME方法(https://github.com/rails/arel/blob/master/lib/arel/visitors/visitor.rb#L15),但它失敗。然後阿雷爾嘗試致電visit_ + object.class.ancestors.find {|klass| respond_to?(DISPATCH[klass], true)}但再次失敗的原因是:

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] 

和阿雷爾沒有任何這名在此列表中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 

其實,我不認爲這是一個非常有用的功能,但我已經問過Aaron Patterson這件事,如果他會喜歡它,我會試着實現它。

+0

想象一下,您有一個Rails 2應用程序,您將此代碼傳遞給Arel無法訪問各個地方的查詢的類,並且它的工作原理是因爲它們有to_s重寫。這一切都停止在Rails 3工作。我知道它是在Rails/Arel功能的邊界:) – Titas 2011-06-17 08:17:03

3

我能夠通過定義to_s方法我的課

class CustomItem 
    def to_s 
    custom_id 
    end 
end 

而且欺騙阿雷爾遊客來治療我的班級爲Fixnum對象

Arel::Visitors::Visitor::DISPATCH[CustomItem] = 'visit_Fixnum' 

使用Rails 3.2.13合作,以解決這個問題。

對於類似字符串的值,您應該模仿String並使用visit_String