2017-04-26 23 views
-2

當我執行User.where(id: 1)時,你能告訴我Active Record如何調用'where'嗎?ActiveRecord如何調用'where'?

我正在檢查Active Record的功能來讀取源代碼並通過pry停止進程。 我可以看到當我執行User.where(id: 1),處理進入 rails/activerecord/lib/active_record/querying.rb

delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or, 
     :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, 
     :having, :create_with, :distinct, :references, :none, :unscope, :merge, to: :all 

「其中」被委派到:所有。 因此它去 rails/activerecord/lib/active_record/scoping/named.rb

def all 
    if current_scope 
    current_scope.clone 
    else 
    default_scoped 
    end 
end 

我不明白這個部分。爲什麼這是所有? 委託可以設置爲類方法嗎?我雖然可以委託給類變量,實例變量。

在作用域/ named.rb所有的方法default_scope後,處理進入rails/activerecord/lib/active_record/relation/query_methods.rb

def where(opts = :chain, *rest) 
    if :chain == opts 
    WhereChain.new(spawn) 
    elsif opts.blank? 
    self 
    else 
    spawn.where!(opts, *rest) 
    end 
end 

爲什麼?是不是where委託給:all?它如何回到where(relation/query_methods.rb)?

+1

出於好奇,你爲什麼關心'where'方法的實現? – MrDanA

+0

出於好奇,你爲什麼關心爲什麼咖啡人關心「where」方法的實現? –

+0

出於好奇,你爲什麼關心爲什麼MrDanA關心我爲什麼關心'where'方法的實現? :) –

回答

4

我不明白這個部分。爲什麼要去all

因爲:

User.where(id: 1) 

等同於:

User.all.where(id: 1) 

這個代表團是爲了簡化API,通過添加隱式調用all時沒有明確提出。

它如何返回到where(relation/query_methods.rb)?

請記住,這是一個代表團,而不是別名。所以,既然:

User.all 

回報:

User.default_scoped 

這意味着,有效,這是被構造的方法鏈:

User.where 
--> User.all.where 
--> User.default_scoped.where 

而且由於User.default_scopedUser::ActiveRecord_Relation對象,其#where的定義確實在rails/activerecord/lib/active_record/relation/query_methods.rb中定義爲:

def where(opts = :chain, *rest) 
    if :chain == opts 
    WhereChain.new(spawn) 
    elsif opts.blank? 
    self 
    else 
    spawn.where!(opts, *rest) 
    end 
end 

......但這只是故事的開始。我們仍然需要爲查詢構建實際的SQL。

Here is a series of blog posts如果您有興趣,那麼可以深入探索,但我認爲這超出了單個StackOverflow答案的範圍。

+0

謝謝你的回答。我可以知道爲什麼'User.where - > User.all.where'?是的,正如你指出的,我認爲委託就像別名。基於此[文檔](https://apidock.com/rails/Module/delegate)委託給:選項指定目標對象。 :都是對象?它看起來像類方法。我仍然無法理解系統如何鏈接像User.all.where這樣的方法是不是因爲委託?我應該檢查另一部分嗎? –

+0

請記住,在ruby中,* everything *是一個對象。即使方法是對象(https://ruby-doc.org/core/Method.html)!!!不要在這裏掛上「對象」這個詞,只要把它看成是「委託'all'的響應,或者換句話說就是'User.where == User.all.where'。 –

+0

這當然與* alias *不同。如果這是一個別名,而不是一個委託,那麼它確實是'User.where == User.all'。但這不是這種情況。 –

相關問題