如何轨协会方法的工作? [英] How do rails association methods work?

查看:139
本文介绍了如何轨协会方法的工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何轨协会方法的工作?让我们考虑这个例子

How do rails association methods work? Lets consider this example

class User < ActiveRecord::Base
   has_many :articles
end

class Article < ActiveRecord::Base
   belongs_to :user
end

现在我可以这样做

@user = User.find(:first)
@user.articles

这取属于该用户我的文章。到目前为止好。

This fetches me articles belonging to that user. So far so good.

现在我还可以继续前进,做一个找到这些文章有一定的条件。

Now further I can go ahead and do a find on these articles with some conditions.

@user.articles.find(:all, :conditions => {:sector_id => 3})

或者干脆声明和协会法像

Or simply declare and associations method like

class User < ActiveRecord::Base
   has_many :articles do
     def of_sector(sector_id)
       find(:all, :conditions => {:sector_id => sector_id})
     end
   end
end

和做

@user.articles.of_sector(3)

现在我的问题是,如何做到这一点查找的ActiveRecord 用联想法对象获取的阵列上工作?因为如果我们执行我们自己的用户称为实例方法文章,写自己的实现,为我们提供了完全相同的结果该协会的方法,对取阵列上找到的ActiveRecord 对象无法工作。

Now my question is, how does this find work on the array of ActiveRecord objects fetched using the association method? Because if we implement our own User instance method called articles and write our own implementation that gives us the exact same results as that of the association method, the find on the fetch array of ActiveRecord objects wont work.

我的猜测是,该协会方法附加一定的属性,以获取对象的数组,能够进一步查询使用查找的ActiveRecord 的方法。什么是code执行这一序列这种情况下?我如何可以验证这一点?

My guess is that the association methods attach certain properties to the array of fetched objects that enables further querying using find and other ActiveRecord methods. What is the sequence of code execution in this this case? How could I validate this?

推荐答案

如何实际上,它是关联对象是一种代理对象。具体的类是<一个href="http://github.com/rails/rails/blob/2-3-stable/activerecord/lib/active%5Frecord/associations/association%5Fproxy.rb">AssociationProxy.如果你看一下这个文件的第52行,你会看到:

How it actually works is that the association object is a "proxy object". The specific class is AssociationProxy. If you look at line 52 of that file, you'll see:

instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }

这样一来,像类方法不再此对象上存在。所以,如果你调用这个对象上,你会得到法缺失。因此,有一个的method_missing 实施了代理对象转发该方法调用的目标:

By doing this, methods like class no longer exist on this object. So if you call class on this object, you'll get method missing. So, there a method_missing implemented for the proxy object that forwards the method call to the "target":

def method_missing(method, *args)
  if load_target
    unless @target.respond_to?(method)
      message = "undefined method `#{method.to_s}' for \"#{@target}\":#{@target.class.to_s}"
      raise NoMethodError, message
    end

    if block_given?
      @target.send(method, *args)  { |*block_args| yield(*block_args) }
    else
      @target.send(method, *args)
    end
  end
end

目标是一个数组,所以当你调用此对象上,它说,它是一个数组,不过这只是因为目标是一个数组,实际的类是AssociationProxy,但你看不到了。

The target is an Array, so when you call class on this object, it says it's an Array, but that's just because the target is an Array, the actual class is an AssociationProxy, but you can't see that anymore.

因此​​,所有你添加的方法,如 of_sector ,被添加到该协会的代理,使他们获得直接调用。类似方法 []和不会对联想的代理定义的,所以他们会发送到目标,这是一个数组。

So all the methods that you add, such as of_sector, get added to the association proxy, so they get called directly. Methods like [] and class aren't defined on the association proxy, so they get sent to the target, which is an array.

要帮你看看这是如何发生的,添加此行的文件217 association_proxy.rb的本地副本:

To help you see how this is happening, add this to line 217 of that file in your local copy of association_proxy.rb:

Rails.logger.info "AssociationProxy forwarding call to `#{method.to_s}' method to \"#{@target}\":#{@target.class.to_s}"

如果您不知道该文件,命令创业板这active_record /协会/ association_proxy会告诉你。现在,当你调用在AssociationProxy,你会看到一个日志消息告诉你它正在发送的目标,这将使我们更清楚发生了什么。这是所有的Rails 2.3.2和其他版本可能会改变。

If you don't know where that file is, the command gem which 'active_record/associations/association_proxy' will tell you. Now when you call class on a AssociationProxy, you will see a log message telling you it is sending that to the target, which should make it clearer what is happening. This is all for Rails 2.3.2 and could change in other versions.

这篇关于如何轨协会方法的工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆