new_record ? メソッドは、ActiveRecord フレームワークのactive_record/persistence.rbにあり、次のようになります。
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' })
最初のステートメントでは、new のようにコンストラクターを呼び出さずに、ヒープにメモリ空間を割り当てます。次に、特別なコンストラクターinit_withを呼び出します。