2012-05-03 88 views
3

如果我要從ActiveRecord調用中獲取關係,數組或其他類型,什麼可以讓我知道?我知道我可以在控制檯中鍵入.class並找出它,但通話本身是否有某些東西能讓我知道我在問什麼?從ActiveRecord查詢返回類型

+0

這將有助於瞭解您想要對結果做什麼。 –

回答

2

你知道,有時Rails的謊言給你 - 所有的魔術師做:)

Rails允許您通過鏈接你的has_many協會構建複雜的查詢。此功能的核心是一堆XXXAssocation(如HasManyAssociation)類。 當您在has_many關聯上致電.class時,您的呼叫實際上適用於HasManyAssociation實例。但這裏的魔法開始:

# collection_proxy.rb 
instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/ } 

Rails的undefs(隱藏)HasManyAssociation實例的方法(除了少數幾個,你可以在正則表達式見),然後使用委派和method_missing您的來電通到一些底層數組(如果你想獲取記錄)或協會本身(如果你鏈接您的協會):

delegate :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, 
      :lock, :readonly, :having, :pluck, :to => :scoped 

    delegate :target, :load_target, :loaded?, :to => :@association 

    delegate :select, :find, :first, :last, 
      :build, :create, :create!, 
      :concat, :replace, :delete_all, :destroy_all, :delete, :destroy, :uniq, 
      :sum, :count, :size, :length, :empty?, 
      :any?, :many?, :include?, 
      :to => :@association 

    def method_missing(method, *args, &block) 
    match = DynamicFinderMatch.match(method) 
    if match && match.instantiator? 
     send(:find_or_instantiator_by_attributes, match, match.attribute_names, *args) do |r| 
     proxy_association.send :set_owner_attributes, r 
     proxy_association.send :add_to_target, r 
     yield(r) if block_given? 
     end 
    end 

    if target.respond_to?(method) || (!proxy_association.klass.respond_to?(method) && Class.respond_to?(method)) 
     if load_target 
     if target.respond_to?(method) 
      target.send(method, *args, &block) 
     else 
      begin 
      super 
      rescue NoMethodError => e 
      raise e, e.message.sub(/ for #<.*$/, " via proxy for #{target}") 
      end 
     end 
     end 

    else 
     scoped.readonly(nil).send(method, *args, &block) 
    end 
    end 

所以,HasManyAssociation例如決定什麼需要自己來處理,並且需要通過隱藏的陣列來完成什麼(class方法不是什麼HasManyAssociation感興趣所以它將在這個隱藏的數組上被調用。結果當然是Array,這是一個小小的欺騙)。

1

以下是我的看法,沿着我認爲重要的知道的線。它主要來自記憶,而且在我的腦海中有一些小小的控制檯實驗,所以我相信如果這個過程能夠得到改善,它可以得到改善。意見歡迎,並要求。

Derived ActiveRecord class --> Record Instance 
    find 

Derived ActiveRecord class | Relation --> Relation 
    where, select, joins, order, group, having, limit, offset, a scope 

Derived ActiveRecord class | Relation --> Record Instance 
    find 

Derived ActiveRecord class | Relation --> Result Array 
    all 

Result Array --> Array 
    to_a 

所以,最重要的是,

  • 你可以連續使用範圍和查詢方法,但直到第一個或全部。首先或所有你不能調用更多的作用域和查詢方法。
  • 當你全部呼叫時,你會得到一個結果數組。一些Array方法已被重新定義爲對數據庫起作用,因此如果您想對返回的數組進行操作,請調用to_a。 Count就是一個例子,如果在結果數組上調用它,它將查詢數據庫中有多少記錄將在數組中再次查詢。