Order
多くのを含むモデルがあるとしましょうproducts
。どの製品が出荷され、どの製品が出荷されていないかを追跡できるようにしたいので、各関係に付随するいくつかのメタデータを追跡したいと思います。これがhas_one
関係である場合、それは単純であり、さらにいくつかのフィールドを挿入するだけです。
モデルとMongoidを使用してhas_many
モデルをきれいに関連付けることで、これをどのように実現できますか?Order
Product
Order
多くのを含むモデルがあるとしましょうproducts
。どの製品が出荷され、どの製品が出荷されていないかを追跡できるようにしたいので、各関係に付随するいくつかのメタデータを追跡したいと思います。これがhas_one
関係である場合、それは単純であり、さらにいくつかのフィールドを挿入するだけです。
モデルとMongoidを使用してhas_many
モデルをきれいに関連付けることで、これをどのように実現できますか?Order
Product
私はこれを自分で解決し、別のモデルOrderProduct
を 2 つの間のプロキシとして使用しました。状態の実装は、state_machine
gem を使用して行われました。最終的に、製品のステート マシンへの多くの呼び出しを 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