在Rails,ActiveRecord::Base.new
用於實例化尚未保存到數據庫中的新記錄:Rails如何實例化從數據庫檢索的對象?
new_user = User.new(name: "Bob")
new_user.new_record? # => true
那麼,如何Rails的實例化從數據庫中檢索的記錄?它是否使用相同的新方法,然後在事後更改像@new_record
這樣的值?或者它使用某種特殊的實例化方法從數據庫中檢索記錄?
在Rails,ActiveRecord::Base.new
用於實例化尚未保存到數據庫中的新記錄:Rails如何實例化從數據庫檢索的對象?
new_user = User.new(name: "Bob")
new_user.new_record? # => true
那麼,如何Rails的實例化從數據庫中檢索的記錄?它是否使用相同的新方法,然後在事後更改像@new_record
這樣的值?或者它使用某種特殊的實例化方法從數據庫中檢索記錄?
The new_record?方法可以在active_record/persistence.rb在ActiveRecord的框架內找到,它看起來像這樣:
def new_record?
@new_record
end
然後,如果你在構造看active_record/core.rb你會看到:
def initialize(attributes = nil, options = {})
@attributes = self.class.initialize_attributes(self.class.column_defaults.deep_dup)
@columns_hash = self.class.column_types.dup
init_internals # here
ensure_proper_type
populate_with_current_scope_attributes
assign_attributes(attributes, options) if attributes
yield self if block_given?
run_callbacks :initialize if _initialize_callbacks.any?
end
如果我們在代碼中挖得深一點:
def init_internals
pk = self.class.primary_key
@attributes[pk] = nil unless @attributes.key?(pk)
@aggregation_cache = {}
@association_cache = {}
@attributes_cache = {}
@previously_changed = {}
@changed_attributes = {}
@readonly = false
@destroyed = false
@marked_for_destruction = false
@new_record = true # here
@mass_assignment_options = nil
end
正如您所看到的,@ new_record默認初始化爲true。
但是存在其中@new_record屬性設置爲true像某些情況下,當你克隆一個記錄:
user = User.first
new_user = user.clone
這將調用initialize_dup方法,看起來像:
def initialize_dup(other) # :nodoc:
# Code removed
@new_record = true
# Code removed
super
end
或當然,當ActiveRecord從數據庫中拉出記錄。我不知道這部分,但我認爲這種方法被稱爲:
def init_with(coder)
@attributes = self.class.initialize_attributes(coder['attributes'])
@columns_hash = self.class.column_types.merge(coder['column_types'] || {})
init_internals
@new_record = false
run_callbacks :find
run_callbacks :initialize
self
end
這可以這樣進行:
post = Post.allocate
post.init_with('attributes' => { 'title' => 'hello world' })
在第一條語句,它在堆上分配內存空間而不用像新的那樣調用構造函數。然後它調用特殊構造函數init_with。
啊,好的,它使用了一種不同的初始化方法,這很有道理。 – Ajedi32
它與instantiate
方法,它使用低級別allocate
方法而不是new
你可以找到這個方法here完成。
這是一個非常廣泛的問題。要麼Google提供一些合適的指南,要麼潛入源代碼。不適合SO,imo。 – Jesper
我問的原因是因爲我想在自己的應用程序中做類似的事情。所以我猜測這種措辭的另一種方法是「如何在Ruby中創建第二個私有初始化器?」 不幸的是,當時我問這個問題,我不知道我真的在尋找第二個初始化程序,我只知道我有一個問題,Rails已經解決了問題,我想知道如何。顯然答案是「他們使用'allocate'與第二個初始化方法。「 – Ajedi32