我有一个模块,它定义了一些方法,并包含在一些Rails模型中。我希望包含模块的模型定义一些特定的方法(就好像我希望它们实现一个接口一样(。
然而,当我希望模型有一个方法,结果是活动记录已经定义的属性时,问题就出现了。
我的代码如下:
Module Mod
included do
# some code...
# require some methods to be implemented by including class
def do_x
raise('not implemented, please override me')
end
def name
raise('not implemented, please override me')
end
end
end
class Supplier < ApplicationRecord
# already has a name attribute
include Mod
# this overrides do_x of mod
def do_x
# some code...
end
end
Supplier类的name
方法实际上被模块Mod的方法覆盖,这不是我想要的行为。
Module Mod
# some code... (within an included block)
# require some methods to be implemented by including class
def do_x
raise('not implemented, please override me')
end
def name
raise('not implemented, please override me')
end
end
class Supplier < ApplicationRecord
include Mod
# this overrides do_x of mod
def do_x
# some code...
end
end
从included
块中删除这些似乎对我有效。
https://api.rubyonrails.org/classes/ActiveSupport/Concern.html#method-i-included解释道:"在基类的上下文中评估给定的块,这样你就可以在这里编写类宏。当你定义多个包含的块时,它会引发一个异常。"它通常用于定义关系、范围、验证
一个相关且有用的Stackoverflow问答:包含Ruby模块的do结束块明确地https://stackoverflow.com/a/28009847/2526423
=======
本地工作示例:
irb(main):070:0> Author.create!
(0.1ms) SELECT sqlite_version(*)
(0.1ms) begin transaction
Author Create (0.5ms) INSERT INTO "authors" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2020-03-29 22:06:28.202124"], ["updated_at", "2020-03-29 22:06:28.202124"]]
(0.8ms) commit transaction
=> #<Author id: 2, name: nil, year: nil, created_at: "2020-03-29 22:06:28", updated_at: "2020-03-29 22:06:28", uid: nil>
irb(main):071:0> author.name
=> nil
irb(main):072:0> author.do_x
class: do_x
=> nil
app/models/author.rb
require 'do_x_mod'
class Author < ApplicationRecord
include DoXMod
def do_x
puts "class: do_x"
end
end
lib/do_x_mod.rb
module DoXMod
# included do
# some code...
# require some methods to be implemented by including class
def do_x
puts "module: do_x"
raise('not implemented, please override me')
end
def name
puts "module: name"
raise('not implemented, please override me')
end
# end
end