0

私が取り組んでいる Ruby プロジェクトでは、次のような mixin アーキテクチャを持つモデル クラスに ActiveRecord スタイルの MVC 機能を追加します。

module Model

  # Classes that mixin this module gain ActiveRecord-style class methods
  # like Model.all, Model.first, Model.last et al.
  #
  # Throughout this module, @@database_bridge will contain a reference to a
  # database ORM bridge, that does the dirty implementation of these methods.

  def all
    # Implementation stuff here, using @@database_bridge as appropriate
  end

  def first
    ...
  end

  # et al

end


class ExampleModel

  extend Model

  # Model-specific implementation goes here...

end

を呼び出すと、データベース内e = ExampleModel.firstの最初のものが に割り当てられます。ExampleModele

@@database_bridge依存性注入を使用して実行時に設定し、それを含むすべてのクラスがextend Model同じ指定された ORM オブジェクトを使用するようにしたいと考えています。

これどうやってするの?

そのクラス変数をオンデマンドで設定するための何らかのヘルパー メソッドを記述できれば、それは素晴らしいことです。

4

2 に答える 2

0

これは答えではありませんが、潜在的な解決策です:を呼び出すことモジュール呼び出すことができます。class_variable_setModule.class_variable_set

したがって、どこかの適切な名前空間で、 を呼び出すヘルパー メソッドを作成できますModule.class_variable_set :@@class_var, "new value"

上記の例では、ヘルパー関数は次のようになります。

def set_database_bridge(new_bridge)
  Model.class_variable_set :@@database_bridge, new_bridge
end

Modelこのソリューションは、 @@database_bridge の名前が変更された場合、ヘルパー関数が壊れてしまうかのように、ヘルパー関数と mixinの実装の間にある程度の結合を作成します。

より疎結合/よりカプセル化されたソリューション (おそらくModelどこかにヘルパー関数をカプセル化する) のアイデアがあれば、それは素晴らしいことです!

于 2013-07-13T14:26:19.563 に答える
0

以前よりも優れた解決策を見つけました。思ったよりもずっと簡単です ( d'oh! ): mixin モジュールでメソッドの前に を付けると、そのメソッドへのパブリック インターフェイスが利用可能になります。self.Module.method

したがって、ステートメントを使用して、モジュールにセッターを追加するだけです。self.attribute_set

上記の例では、上記のアプローチにより次のコードが生成されます。

module Model

  # Classes that mixin this module gain ActiveRecord-style class methods
  # like Model.all, Model.first, Model.last et al.
  #
  # Throughout this module, @@database_bridge will contain a reference to a
  # database ORM bridge, that does the dirty implementation of these methods.

  def all
    # Implementation stuff here, using @@database_bridge as appropriate
  end

  def first
    ...
  end

  def self.set_database_bridge(ref_to_new_bridge)
    @@database_bridge = ref_to_new_bridge
    ## any additional intialisation/sanitisation logic goes here
  end

  # et al

end


class ExampleModel

  extend Model

  # Model-specific implementation goes here...

end

を呼び出すと、新しいデータベース ブリッジModel.set_database_bridgeを渡すことができます。

ヘルパー関数で実際に初期化またはサニタイズ ロジックが必要ない場合は、別のより洗練されたアプローチがあります -ブロックに an を追加しattr_accessorclass << selfます。

module Model

  # ...

  class << self
    attr_accessor :database_bridge
  end

end

このようにして、Ruby の標準設定メソッド:を呼び出すことができますModel.database_bridge = the_new_bridge

甘い。

于 2013-07-13T14:55:52.107 に答える