# 查询得到。从 SQL 层面转向到 Ruby 层面
def find_by_sql(sql, binds = [])
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds)
column_types = result_set.column_types.dup
# ...
result_set.map { |record| instantiate(record, column_types) }
end
def instantiate(attributes, column_types = {})
klass = discriminate_class_for_record(attributes)
attributes = klass.attributes_builder.build_from_database(attributes, column_types)
klass.allocate.init_with('attributes' => attributes, 'new_record' => false)
end
def allocate
define_attribute_methods
super
end
def init_with(coder)
@attributes = coder['attributes']
init_internals
@new_record = coder['new_record']
self.class.define_attribute_methods
_run_find_callbacks
_run_initialize_callbacks
self
end
User.new(first_name: 'Jamie')
def initialize(attributes = nil, options = {})
@attributes = self.class._default_attributes.dup
self.class.define_attribute_methods
init_internals
initialize_internals_callback
init_attributes(attributes, options) if attributes
yield self if block_given?
_run_initialize_callbacks
end
user = User.first
new_user = user.clone
user.name # => "Bob"
new_user.name = "Joe"
user.name # => "Joe"
user.object_id == new_user.object_id # => false
user.name.object_id == new_user.name.object_id # => true
user.name.object_id == user.dup.name.object_id # => false
class Post < ActiveRecord::Base
end
coder = {}
Post.new.encode_with(coder)
coder # => {"attributes" => {"id" => nil, ... }}
class Post < ActiveRecord::Base
end
post = Post.allocate
post.init_with('attributes' => { 'title' => 'hello world' })
post.title # => 'hello world'