Ruby on rails 如何将模块包含到类中,以使模块覆盖该类?
有没有一种方法可以将模块包含到类中,从而使模块的 方法重写类的方法?例如:Ruby on rails 如何将模块包含到类中,以使模块覆盖该类?,ruby-on-rails,ruby,Ruby On Rails,Ruby,有没有一种方法可以将模块包含到类中,从而使模块的 方法重写类的方法?例如: module UpcasedName def name @name.upcase end end class User attr_accessor :name include UpcasedName end u = User.new u.name = 'john' puts u.name # outputs 'john', not 'JOHN' 在上面的例子中,u.name是“john”,而
module UpcasedName
def name
@name.upcase
end
end
class User
attr_accessor :name
include UpcasedName
end
u = User.new
u.name = 'john'
puts u.name # outputs 'john', not 'JOHN'
在上面的例子中,u.name是“john”,而不是“john”。我知道如果我
扩展用户对象,而不是将模块包含到类中
行得通
module UpcasedName
def name
@name.upcase
end
end
class User
attr_accessor :name
end
u = User.new
u.name = 'john'
u.extend UpcasedName
puts u.name # outputs 'JOHN'
但是,我想在类级别而不是对象级别包含模块。现在有几种方法可以做到这一点。第一个也是最基本的方法是使用ActiveSupport中的alias_method_chain
require 'activesupport'
module UpcasedName
def self.included( base )
base.alias_method_chain :name, :upcase
end
def name_with_upcase
@name.upcase
end
end
class User
attr_accessor :name
include UpcasedName
end
u = User.new
u.name = 'john'
puts u.name
您发布的方法实际上与Bruce Williams发布的方法类似:
如果你真的对此很坚决,你可以遵循Yehuda Katz在这里发布的方法:Include类似于从另一个类继承,在这个意义上,你将模块包含到其中的类的方法优先于包含的方法。您甚至可以在类中调用super来访问模块中的方法:
class User
attr_accessor :name
def name
super
end
include UpcasedName
end
u = User.new
u.name = 'john'
puts u.name # outputs 'JOHN'
这里有一篇关于它的文章:根据ucron的回答,在没有activesupport的情况下可以这样做,如下所示:
module UpcasedName
def self.included(base)
base.send :alias_method, :name_without_feature, :name
base.send :alias_method, :name, :name_with_upcase
end
def name_with_upcase
@name.upcase
end
end
class User
attr_accessor :name
include UpcasedName
end
u = User.new
u.name = 'john'
puts u.name
这里的问题是
attr\u accessor
创建了一个User.name方法来覆盖UpcasedName.name方法,因此一种解决方案是使用attr\u writer
:
module UpcasedName
def name
@name.upcase
end
end
class User
attr_writer :name
include UpcasedName
end
u = User.new
u.name = 'john'
puts u.name # outputs 'JOHN'
它可能并不总是一个选项,但我认为最好是将类的方法移动到它自己的模块中,并将该模块混合回类中。我觉得这更干净
谢谢您的参考。但是,base.alias\u method\u chain:name,:upcase需要更改为base.alias\u method\u chain:name,:name\u with\u upcase