4

クラス Ryte::Theme があります。クラスで included_modules を呼び出すと、返されます (省略):

[Ryte::Bundleable::Core、Ryte::Bundleable::Validators、Ryte::Bundleable::Builder、ActiveModel::Validations::HelperMethods、ActiveModel::Validations、ActiveSupport::Callbacks、Ryte::Bundleable]

Ryte::Theme は、単一のモジュール Ryte::Bundleable を介してネストされたモジュールを取り込みます。関連するクラスとモジュールの定義は次のとおりです。

class Ryte::Theme
  include Ryte::Bundleable
end


module Ryte::Bundleable
  extend ActiveSupport::Concern

  included do
    include ActiveModel::Validations
    include Ryte::Bundleable::Builder
    include Ryte::Bundleable::Validators
    include Ryte::Bundleable::Core
  end
end

これを考えると、次の応答を受け取るのはなぜですか。

Ryte::Theme.include?(Ryte::Theme::Validators)
=> true

この追加モジュールは (まだ) 含めていません。これは、included_modules 応答で明らかです。これは ActiveSupport の懸念に関連していますか? Ryte::Theme::Validators をインクルードして mixin できるようにしたいのですが、すでにインクルードされていると見なされるため、「再び」インクルードしません (それが本当ならそうすべきではないため)。そのため、インクルードをクラス定義に追加すると、次のように取り残されます。

class Ryte::Theme
  include Ryte::Bundleable
  include Ryte::Theme::Validators # <- Does not load
end

この追加モジュール Ryte::Theme::Validators も混ざらないのはなぜですか?

追加した

わかりました:

1.9.3p194 :005 > Ryte::Bundleable::Validators == Ryte::Theme::Validators
 => true 

奇妙な..これはなぜですか?

4

1 に答える 1

6

更新: これActiveSupport::Concern に関連しています (以下を参照)。

次のことを試してください。

# initialize constants
class A; end                               # class Ryte
module A::B; end                           # module Ryte::Bundleable
module A::B::C; end                        # module Ryte::Bundleable::Validators

module A::B                                # module Ryte::Bundleable
  def self.include(base)
    base.class_eval do
      include A::B::C                      # include Ryte::Bundleable::Validators
    end
  end
end

class D                                    # class Ryte::Theme
  include A::B                             # include Ryte::Bundleable
end

A::B::C == D::C                            #=> true

これは、モジュールとクラスの名前空間の付け方が原因で発生します。A::B::Cの内部からインクルードするA::Bと、モジュール名はモジュール自体に対して相対的に参照CされますValidators。したがって、という名前のモジュールを含めるのではなく、A::B他のクラスに含めると(つまり これがtrue と評価される理由です。DA::B::CRyte::Bundleable::ValidatorsCValidatorsRyte::Bundleable::Validators == Ryte::Theme::Validators

ただし、上記の例では:

D.include?(A::B::C)                       #=> false

ここでActiveSupport::Concern本題です。上記のモジュールA::Bを次のように再定義します。

module A::B                                # module Ryte::Bundleable
  extend ActiveSupport::Concern

  included do
    include A::B::C                      # include Ryte::Bundleable::Validators
  end
end

D.include?(A::B::C)そして、今では true と評価されることがわかります。なぜこれが起こるのかは正直わかりませんが、上記の名前空間と関係があるに違いありません。

于 2012-09-09T06:30:55.443 に答える