Rails3 Arel посещения пользовательских классов - PullRequest
5 голосов
/ 15 июня 2011

У меня есть собственный класс, но я хочу иметь возможность передать его Арелю и позволить ему разрешить его запрашиваемую часть.

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, так что он бы понял, что Арель хочет получить от него имя?

В настоящее время я работаю с:

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

Ответы [ 2 ]

5 голосов
/ 16 июня 2011

Я думаю, что сейчас это невозможно.Давайте попробуем выяснить, почему.

Когда вы пытаетесь передать свой пользовательский объект методу 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

На самом деле, я не думаю, что это очень полезная функция, но я спросил об этом Аарона Паттерсона, и если ему понравится, я постараюсь реализовать его.

3 голосов
/ 10 июня 2013

Мне удалось обойти эту проблему, определив метод 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.

...