使用 undef_method,遇到的一个问题,想不明白 rails 是如何处理的,不知哪位大神可以给到一个解答。
场景如下:
user model 含有字段 name,同时 include 了一个 module UserAddon,使用 undef_method 来禁止调用引入的 name 方法,按照 undef_method 的定义, 此时 User 的对象调用 name 时,应该会报错,但是进入终端后,发现没有,反而返回了正确的结果。
代码如下:
## app/models/user.rb
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string(254)
# name :string(254)
# password_digest :string(254)
# created_at :datetime not null
# updated_at :datetime not null
class User < ActiveRecord
include UserAddon
undef_method :name
end
## app/models/user_addon.rb
module UserAddon
def name
"hello"
end
end
这时,rails c 进入 console:
user = User.first
# => #<User id: 1, name: "admin", email: "[email protected]", created_at:……>
user.methods.include?(:name)
# => false
user.name
# => "admin"
$ user.name
# => Couldn't locate a definition for user.name
user.respond_to?(:name)
# => true
使用 pry 的$ ,找不到 user.name 的定义,但是执行 user.name 却返回了正确的结果,此时一定调用了 method_missing。但是,如何查看 rails 是如何实现的呢?
ruby 元编程中在有关 rails 的属性方法中曾经提到,当第一次访问一个属性时,这个属性是一个幽灵方法,ActiveRecord::Base # method_missing() 会把它转换成一个真实的方法,同时创建出读,写,查询方法,比如上面的 name,会创建 name, name=, name?,这样下次就可以直接调用。
但是,这里很显然,user.methods.include?(:name) 返回了 false,这里并没有创建 name 这个方法,那么 rails 是如何让 user.name 返回了"admin"的呢?
我看了下 rails 的attribute_methods中 method_missing 部分的代码,苦于水平有限,没看懂这里到底是如何实现的,不知哪位大神可以给到一个清晰的解答或者指个方向?thx!