web-dev-qa-db-fra.com

Comment puis-je inclure un module dans un autre module (code Refactor AASM et états personnalisés dans le module)

J'essaie de refactoriser un modèle superfat qui a pas mal de lignes de code ActsAsStateMachine liées aux états et aux transitions, et j'espérais refactoriser cela en un module appelé 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

Et puis dans le modèle

include CallStates

Ma question concerne la façon d'inclure le comportement du module dans un module de telle sorte qu'un seul module puisse être inclus dans le modèle. J'ai essayé class_eval faire aussi bien en vain. Merci pour toutes vos idées perspicaces à ce sujet.

30
Mike

Vous ne pouvez pas inclure un module dans un autre exactement, mais vous pouvez dire à un module d'inclure d'autres modules dans la classe dans laquelle il est inclus:

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

Il est préférable de ne le faire que si Bmodule est en fait des données nécessaires au fonctionnement d'Amodule, sinon cela peut entraîner de la confusion car il n'est pas explicitement inclus dans MyClass.

42
Pan Thomakos

Vous incluez un module dans un autre module en ... incluant un module dans un autre module, bien sûr!

module Bmodule
  def greet
    puts 'hello world'
  end
end

module Amodule
  include Bmodule
end

class MyClass
  include Amodule
end

MyClass.new.greet # => hello world
19
Jörg W Mittag

Rails

Pour Rails, vous voudrez faire quelque chose comme ceci:

module_b.rb

module ModuleB
  extend ActiveSupport::Concern

  included do
    include ModuleA
  end
end

mon_modèle.rb

class MyModel < ActiveRecord::Base

  include ModuleB

end

ModuleA est inclus dans ModuleB, qui est ensuite inclus dans MyModel classe.

15
Joshua Pinter

J'aime mieux cette syntaxe:

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
8
Tom Rossi