我有Ruby类,我想要包含类和实例方法。按照here描述的模式,我目前正在使用以下内容:
class SomeObject
include SomeObject::Ability
def self.some_builder_method(params)
# use some_class_method ...
end
end
module SomeObject::Ability
module ClassMethods
def some_class_method(param)
# ...
end
end
def self.included(klass)
klass.extend(ClassMethods)
end
def some_instance_method
# ...
end
end
我宁愿不制作两个独立的模块(一个被包含,另一个被扩展),因为我模块中的所有方法在逻辑上都是一致的。另一方面,这种模式a)要求我定义一个额外的ClassMethods
模块,b)要求我为每个模块编写样板self.included
方法。
有更好的方法吗?
编辑1 :我找到了另一种方法,但我不确定这是否比第一种更好。
module Concern
def included(base)
# Define instance methods.
instance_methods.each do |m|
defn = instance_method(m)
base.class_eval { define_method(m, defn) }
end
# Define class methods.
(self.methods - Module.methods).each do |m|
unless m == __method__
base.define_singleton_method(m, &method(m))
end
end
end
end
module SomeModule
extend Concern
def self.class_m
puts "Class"
end
def instance_m
puts "Instance"
end
end
class Allo
include SomeModule
end
Allo.class_m # => "Class"
Allo.new.instance_m # => "Instance"
答案 0 :(得分:4)
如果我理解正确,你真的只想使用ActiveSupport::Concern
:
module PetWorthy
extend ActiveSupport::Concern
included do
validates :was_pet, inclusion: [true, 'yes']
end
def pet #instance method
end
module ClassMethods
def find_petworthy_animal
# ...
end
end
end
class Kitty
include PetWorthy
end
Kitty.find_petworthy_animal.pet
如果您没有任何触发包含的行为,那么您(显然希望)不需要使用included
方法,但我只是为了演示而将其放入。