如何将模块包含到另一个模块中(将AASM代码和自定义状态重构为模块)

时间:2011-02-06 17:29:45

标签: ruby refactoring

我正在尝试重构一个超级脂肪模型,它有很多与状态和转换相关的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也无济于事。感谢您对此事的任何深刻见解。

4 个答案:

答案 0 :(得分:41)

您不能准确地将一个模块包含在另一个模块中,但是您可以告诉模块在其所包含的类中包含其他模块:

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中。

答案 1 :(得分:19)

您将模块包含到另一个模块中......当然,将模块包含在另一个模块中!

module Bmodule
  def greet
    puts 'hello world'
  end
end

module Amodule
  include Bmodule
end

class MyClass
  include Amodule
end

MyClass.new.greet # => hello world

答案 2 :(得分:14)

滑轨

对于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类中。

答案 3 :(得分:8)

我最喜欢这种语法:

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