Зачем использовать ActiveSupport :: Concern вместо простого модуля? - PullRequest
0 голосов
/ 26 ноября 2018

Я никогда не понимал, почему нужно использовать ActiveSupport :: Concern используется для mixins вместо простого модуля.Есть ли простой ответ на то, что ActiveSupport :: Concern предоставляет (по крайней мере, в Rails 5), что будет делать простой модуль без использования ActiveSupport :: Concern?

1 Ответ

0 голосов
/ 26 ноября 2018

С https://api.rubyonrails.org/classes/ActiveSupport/Concern.html:

Типичный модуль выглядит следующим образом:

module M
  def self.included(base)
    base.extend ClassMethods
    base.class_eval do
      scope :disabled, -> { where(disabled: true) }
    end
  end

  module ClassMethods
    ...
  end
end

Используя ActiveSupport::Concern, вышеприведенный модуль может быть записан как:

require 'active_support/concern'

module M
  extend ActiveSupport::Concern

  included do
    scope :disabled, -> { where(disabled: true) }
  end

  class_methods do
    ...
  end
end

Более того, он изящно обрабатывает зависимости модуля.Учитывая модуль Foo и модуль Bar, который зависит от первого, мы обычно пишем следующее:

module Foo
  def self.included(base)
    base.class_eval do
      def self.method_injected_by_foo
        ...
      end
    end
  end
end

module Bar
  def self.included(base)
    base.method_injected_by_foo
  end
end

class Host
  include Foo # We need to include this dependency for Bar
  include Bar # Bar is the module that Host really needs
end

Но почему Host следует заботиться о зависимостях Bar, а именноFoo?Мы могли бы попытаться скрыть их от Host напрямую, включая Foo в Bar:

module Bar
  include Foo
  def self.included(base)
    base.method_injected_by_foo
  end
end

class Host
  include Bar
end

К сожалению, это не сработает, поскольку при включении Foo его основой является Bar модуль, а не Host класс.С ActiveSupport::Concern зависимости модуля правильно разрешены:

require 'active_support/concern'

module Foo
  extend ActiveSupport::Concern
  included do
    def self.method_injected_by_foo
      ...
    end
  end
end

module Bar
  extend ActiveSupport::Concern
  include Foo

  included do
    self.method_injected_by_foo
  end
end

class Host
  include Bar # It works, now Bar takes care of its dependencies
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...