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

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")

 

转载于:https://www.cnblogs.com/musibevan/p/5950107.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值