如果我要从 ActiveRecord 调用中返回 Relation、Array 或其他类型,我会知道什么?我知道我可以在控制台中输入 .class 并弄清楚,但是调用本身是否有一些东西可以让我知道我在问什么?
问问题
4149 次
2 回答
2
你知道,Rails 有时会对你撒谎——所有魔术师都会这样 :)
Rails 允许您通过链接has_many
关联来构建复杂的查询。这个功能的核心是一堆 XXXAssociation (like HasManyAssociation
) 类。例如,当您调用.class
关联has_many
时,实际上会应用您的调用HasManyAssociation
。但这里是神奇的开始:
# collection_proxy.rb
instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/ }
Rails 取消定义(隐藏)HasManyAssociation
实例方法(除了少数,正如您在正则表达式中看到的那样),然后使用委托并将method_missing
您的调用传递给某个底层数组(如果您试图获取记录)或关联本身(如果您要链接您的关联):
delegate :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from,
:lock, :readonly, :having, :pluck, :to => :scoped
delegate :target, :load_target, :loaded?, :to => :@association
delegate :select, :find, :first, :last,
:build, :create, :create!,
:concat, :replace, :delete_all, :destroy_all, :delete, :destroy, :uniq,
:sum, :count, :size, :length, :empty?,
:any?, :many?, :include?,
:to => :@association
def method_missing(method, *args, &block)
match = DynamicFinderMatch.match(method)
if match && match.instantiator?
send(:find_or_instantiator_by_attributes, match, match.attribute_names, *args) do |r|
proxy_association.send :set_owner_attributes, r
proxy_association.send :add_to_target, r
yield(r) if block_given?
end
end
if target.respond_to?(method) || (!proxy_association.klass.respond_to?(method) && Class.respond_to?(method))
if load_target
if target.respond_to?(method)
target.send(method, *args, &block)
else
begin
super
rescue NoMethodError => e
raise e, e.message.sub(/ for #<.*$/, " via proxy for #{target}")
end
end
end
else
scoped.readonly(nil).send(method, *args, &block)
end
end
所以,HasManyAssociation
instance 自己决定要处理什么以及需要通过隐藏数组来完成什么 (class
方法不是什么HasManyAssociation
感兴趣的,所以它会在这个隐藏数组上调用。结果当然是Array
,这有点欺骗)。
于 2012-05-03T11:15:01.630 回答
1
这是我的看法,我认为重要的是要知道。它主要来自记忆,并通过一些控制台实验从我的脑海中浮出水面,所以我确信如果它得到传递,它可以得到改进。欢迎评论和请求。
Derived ActiveRecord class --> Record Instance
find
Derived ActiveRecord class | Relation --> Relation
where, select, joins, order, group, having, limit, offset, a scope
Derived ActiveRecord class | Relation --> Record Instance
find
Derived ActiveRecord class | Relation --> Result Array
all
Result Array --> Array
to_a
所以重要的是,
- 您可以链接范围和查询方法,但仅限于 first 或 all。毕竟你不能调用更多的范围和查询方法。
- 当你调用 all 时,你会得到一个结果数组。Array 的一些方法被重新定义为作用于数据库,所以如果你想对返回的数组进行操作,调用 to_a。一个例子是 count,如果在 Result Array 上调用它,它将查询数据库,如果再次查询该数组,则该数组中有多少条记录。
于 2012-05-03T11:00:19.717 回答