0

私のアプリでは、ランタイムでモデルを作成し、それらを現在のモデルに埋め込む必要があります。これらの作成されたモデルは、モデルを埋め込むこともできます。これらの埋め込み可能なモデルの共通点を得るために、それらに含めることができるモジュールを作成しました。

例えば:

module CommonMethods
  def make_self(context)
    if context['nested']
      inner_klass_name = context['name'].classify
      inner_klass = Object.const_set(inner_klass_name, Class.new)
      inner_klass.class_eval <<-ENDSRC
        include Mongoid::Document
        include CommonMethods

        embedded_in :#{@mclass_name.underscore}, :inverse_class_name => "#{@mclass_name}"

        after_initialize :start_make_self

        def start_make_self
          @mclass_name = "#{inner_klass_name}"
          make_self(#{context['nested_context']})
        end
      ENDSRC

      self.class_eval <<-ENDSRC
        embeds_one :#{context['name']}, :inverse_class_name => "#{inner_klass_name}"
      ENDSRC
    else
      self.class_eval <<-ENDSRC
        field :#{context['name']}, :type => String
      ENDSRC
    end
  end
end

class MModel
  include Mongoid::Document
  include CommonMethods

  field :context_id, :type => String
  after_initialize :start_make_self

  def start_make_self
    context = Context.where(:uid => self.context_id)
    @mclass_name = "MModel"
    make_self(context.attributes)
  end
end

したがって、のフィールドMModelとその埋め込みドキュメントは、Contextモデルを使用して作成されます。

ここでの問題は、ネストされていないフィールドが作成され、その場で検証できる一方で、ネストされた(埋め込まれた)モデルには問題があるように見えることです。新しいフィールドが作成されたときに初期化されずMModel、データが渡されます。最初のレベルは機能しますが、それより下のレベルは機能しません。

これに関するヒントはありますか?

4

1 に答える 1

0

クラスのコンストラクターをオーバーライドすることで、この問題を部分的に解決しました。

class MModel
  include Mongoid::Document
  include CommonMethods

  field :context_id, :type => String

  def initialize(attrs=nil)
    context = Context.where(:uid => attrs[:context_id])
    @mclass_name = "MModel"
    make_self(context.attributes)
    super
  end
end

同様にinner_klassについても同様です。残っている唯一の問題は、リレーションと検証が機能している間(embeds_oneなど)、ランタイムフィールド宣言が機能していないように見えることです。たとえば、typeをanとして宣言されたフィールドはArray尊重されません。私は同じもののカスタム検証を提供することによって一時的にそれを回避しました。

于 2012-08-02T05:38:33.567 に答える