1

假设我有一个Order模型,其中包含许多products. 我希望能够跟踪哪些产品已发货,哪些未发货,因此我想跟踪与每个关系相关的一些元数据。如果这是一个has_one关系,那么它会很简单,只需插入更多的字段。

如何使用 Mongoid 干净地通过模型和模型has_many之间的关系来实现这一点?OrderProduct

4

1 回答 1

0

我自己解决了这个问题,我使用另一个模型OrderProduct作为两者之间的代理。状态的实现是使用state_machinegem 完成的。我最终将很多对产品状态机的调用封装在 Order 模型中。这使我可以在订单实例上调用.product_state(product)或调用类似的东西。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 回答