1

Order多くのを含むモデルがあるとしましょうproducts。どの製品が出荷され、どの製品が出荷されていないかを追跡できるようにしたいので、各関係に付随するいくつかのメタデータを追跡したいと思います。これがhas_one関係である場合、それは単純であり、さらにいくつかのフィールドを挿入するだけです。

モデルとMongoidを使用してhas_manyモデルをきれいに関連付けることで、これをどのように実現できますか?OrderProduct

4

1 に答える 1

0

私はこれを自分で解決し、別のモデルOrderProductを 2 つの間のプロキシとして使用しました。状態の実装は、state_machinegem を使用して行われました。最終的に、製品のステート マシンへの多くの呼び出しを Order モデルにラップしました。.product_state(product)これにより、 orのようなものをcan_cancel_product?(product)注文インスタンスで呼び出すことができます。

注文

class Order
  include Mongoid::Document
  include Mongoid::Timestamps

  field :state, type: String

  embeds_many :order_products

  state_machine initial: :open do
    ...
  end

  def products
    order_products.map do |op|
      op.product
    end.freeze
  end

  def add_product(product)
     OrderProduct.create({_product: product._id, order: self})
  end

  def remove_product(product)
    order_products.delete find_order_product(p)
  end

  #wrapper for product events
  OrderProduct.new.state_paths.events.each do |event|
    define_method "#{event}_product" do |product|
      find_order_product(product).send(event)
    end
    define_method "can_#{event}_product?" do |product|
      find_order_product(product).send("can_#{event}?")
    end
  end

  #wrapper for product states
  OrderProduct.state_machine.states.map(&:name).each do |state|
    define_method "product_#{state}?" do |product|
      find_order_product(product).send("#{state}?")
    end
  end

  #wrapper for product current state
  def product_state(product)
    find_order_product(product).state
  end

  private
    def find_order_product(p)
      order_products.at(order_products.index do |op|
        op.product == p
      end)
    end

end

注文商品

class OrderProduct

  include Mongoid::Document

  embedded_in :order
  field :_product, type: Moped::BSON::ObjectId

  state_machine initial: :open do
    ....
  end

  def product
    Product.find(_product)
  end
  def product=(product)
    _product = (product._id)
  end

end
于 2012-12-06T09:22:16.410 に答える