微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ruby-on-rails – Rails如何实例化从数据库中检索的对象?

在Rails中,ActiveRecord :: Base.new用于实例化尚未保存到数据库的新记录:

new_user = User.new(name: "Bob")
new_user.new_record? # => true

那么Rails如何实例化从数据库中检索的记录呢?它是否使用相同的新方法,然后在事后更改@new_record之类的值?或者它是否对从数据库中检索的记录使用某种特殊的实例化方法

解决方法

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' })

在第一个语句中,它在堆上分配内存空间而不像新的那样调用构造函数.然后它调用特殊构造函数init_with.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐