Как включить модуль в другой модуль (код Refactor AASM и пользовательские состояния в модуль) - PullRequest
27 голосов
/ 06 февраля 2011

Я пытаюсь провести рефакторинг супержирной модели, которая содержит довольно много строк кода 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 ]

42 голосов
/ 06 февраля 2011

Вы не можете точно включить один модуль в другой, но вы можете указать модулю включить другие модули в класс, в который он включен:

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.

19 голосов
/ 07 февраля 2011

Вы включаете модуль в другой модуль путем ... включения модуля в другой модуль, конечно!

module Bmodule
  def greet
    puts 'hello world'
  end
end

module Amodule
  include Bmodule
end

class MyClass
  include Amodule
end

MyClass.new.greet # => hello world
14 голосов
/ 11 января 2015

Рельсы

Для 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.

8 голосов
/ 18 июля 2014

Мне больше нравится этот синтаксис:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...