Как включить модуль в другой модуль (Refactor AASM code и пользовательские состояния в модуль)
Я пытаюсь реорганизовать модель суперфата, которая имеет довольно много строк кода ActsAsStateMachine, связанных с состояниями и переходами, и я надеялся реорганизовать это на вызов модуля CallStates.
#in lib/CallStates.rb
module CallStates
module ClassMethods
aasm_column :status
aasm_state :state1
aasm_state :state2
aasm_state :state3
end
def self.included(base)
base.send(:include, AASM)
base.extend(ClassMethods)
end
end
А затем в модели
include CallStates
Мой вопрос касается включения модуля в модуль таким образом, чтобы один модуль мог быть включен в модель. Я пробовал class_eval делать тоже безрезультатно. Спасибо за любые проницательные мысли, которые вы имеете по этому поводу.
Ответы
Ответ 1
Вы не можете включить один модуль в другой точно, но вы можете сказать модулю о включении других модулей в класс, в который он включался:
module Bmodule
def greet
puts 'hello world'
end
end
module Amodule
def self.included klass
klass.class_eval do
include Bmodule
end
end
end
class MyClass
include Amodule
end
MyClass.new.greet # => hello world
Лучше всего сделать это, только если Bmodule - это данные, необходимые для функционирования Amodule, иначе это может привести к путанице, поскольку оно явно не включено в MyClass.
Ответ 2
Вы включаете модуль в другой модуль... включая модуль в другой модуль, конечно!
module Bmodule
def greet
puts 'hello world'
end
end
module Amodule
include Bmodule
end
class MyClass
include Amodule
end
MyClass.new.greet # => hello world
Ответ 3
Рельсы
Для Rails вам нужно сделать что-то вроде этого:
module_b.rb
module ModuleB
extend ActiveSupport::Concern
included do
include ModuleA
end
end
my_model.rb
class MyModel < ActiveRecord::Base
include ModuleB
end
ModuleA
включается в ModuleB
, который затем включается в класс MyModel
.
Ответ 4
Мне нравится этот синтаксис лучший:
module Bmodule
def greet
puts 'hello world'
end
end
module Amodule
def self.included(receiver)
receiver.send :include, Bmodule
end
end
class MyClass
include Amodule
end
MyClass.new.greet # => hello world