码迷,mamicode.com
首页 > 其他好文 > 详细

rails内的class关于添加了has_many或者belongs_to后如何动态添加一些额外的方法 ?

时间:2016-10-11 18:18:33      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:

rails版本5.0.0.1

比如有如下的两个类

class User < ActiveRecord::Base
  has_many :posts

end

class Post < ActiveRecord::Base
  belongs_to :user

end

这个时候有一个user

user = User.take

然后可以使用user.posts来找到属于user的所有的posts,同理如果有一个post也可以通过post.user来找到属于它自己的user

这个时候不禁想问,这个user.post方法是怎么来的呢?

ActiveRecord::Core里有个generated_association_methods方法

def generated_association_methods
  @generated_association_methods ||= begin
    mod = const_set(:GeneratedAssociationMethods, Module.new)
    include mod
    mod
  end
end

当你的rails加载你的class就会执行这个方法(比如加载了User class),并新建一个xxx::GeneratedAssociationMethods的module(加载User class就创建了属于user自己的module:User::GeneratedAssociationMethods),然后通过include方式将xxx::GeneratedAssociationMethods module加载进入到你的class里。而这个module就会用来存放user.posts类似这样的方法。

User class中添加的has_many :posts就在加载class时执行一系列方法到2个方法:self.define_readers(mixin, name)self.define_writers(mixin, name) 

这里的两个参数对应的分别为mixin: User, name: posts

具体代码如下:

 

    def self.define_readers(mixin, name)
      mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
        def #{name}(*args)
          association(:#{name}).reader(*args)
        end
      CODE
    end

    def self.define_writers(mixin, name)
      mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
        def #{name}=(value)
          association(:#{name}).writer(value)
        end
      CODE
    end

这两个方法就是动态地添加.posts(*args)和.posts=(value) 2个user的实例方法。

class_eval 这个方法会在一个已存在的类的上下文中执行一个块,并且会修改这个类的内容(《ruby元编程》的解释)。

如下代码会添加.posts(*args)到User::GeneratedAssociationMethods模块里

mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
        def #{name}(*args)
          association(:#{name}).reader(*args)
        end
      CODE

 

如果按照《ruby元编程》的知识的话,可以这样改写

mixin.class_eval do
  define_method(name) do |*args|
    association(name.to_sym).reader(*args)
  end
end

 又或者可以一行改写

mixin.class_eval("def #{name}(*args); association(:#{name}).reader(*args); end")

 

rails内的class关于添加了has_many或者belongs_to后如何动态添加一些额外的方法 ?

标签:

原文地址:http://www.cnblogs.com/musibevan/p/5950107.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!