Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 当子对象满足特定条件时更新父对象_Ruby On Rails - Fatal编程技术网

Ruby on rails 当子对象满足特定条件时更新父对象

Ruby on rails 当子对象满足特定条件时更新父对象,ruby-on-rails,Ruby On Rails,我有两种型号-订单和项目: order.rb: class Order < ActiveRecord::Base has_many :items end 订单模式: t.string "status" 当用户收到项目时,项目的状态将标记为已发货。那么,在所有项目的状态都更新为“已发货”的情况下,如何将订单状态更新为“已完成” 我喜欢这样的东西: class Item < ActiveRecord::Base def complete_order order

我有两种型号-订单和项目:

order.rb:

class Order < ActiveRecord::Base
  has_many :items
end
订单模式:

 t.string   "status"

当用户收到项目时,项目的状态将标记为已发货。那么,在所有项目的状态都更新为“已发货”的情况下,如何将订单状态更新为“已完成”

我喜欢这样的东西:

class Item < ActiveRecord::Base
  def complete_order
     order.complete if all_items_shipped?
  end

  def shipped?
    status == 'shipped'
  end

  private

  def all_items_shipped?
    order.items.all?(&:shipped?)
  end
end

class Order < ActiveRecord::Base
  def complete
    update status: 'complete'
  end
end
class项

然后调用
项目。每次
项目
标记为
已发货
时,完成订单
。您需要更新
项目
表以包含一个,将其与
订单
关联:

$ rails g new migration AddOrderIDToItems

#db/migrate/add_order_id_to_items______.rb
class AddOrderIdToItems < ActiveRecord::Migration
   def change
      add_column :items, :order_id, :integer
   end
end

$ rake db:migrate

真正的解决方法是创建一个
has\u many:通过
关系,将许多
项目关联到许多
订单。通过这种方式,您可以将每个
OrderItems
标记为“已发货”:

然后,您可以使用以下设置订单是否已“完成”:


我应该在哪里调用
项目。完成订单
还是像更新后那样使用回调?如果我得到了另一个条件,项目的状态=“退款”,那么如果2个项目是“已发货”,1个项目是“退款”,订单的状态应该标记为“未完成”。谢谢。您说过:当用户收到商品时,商品的状态将标记为已发货,因此您可以调用
Item。在更新商品状态的同一时刻/地点完成订单。对于第二个问题,我将把它添加到问题的主体中,因为它实际上是另一个特性。您可以用类似的方式复制逻辑来处理该情况。
class Item < ActiveRecord::Base
  def complete_order
     order.complete if all_items_shipped?
  end

  def shipped?
    status == 'shipped'
  end

  private

  def all_items_shipped?
    order.items.all?(&:shipped?)
  end
end

class Order < ActiveRecord::Base
  def complete
    update status: 'complete'
  end
end
$ rails g new migration AddOrderIDToItems

#db/migrate/add_order_id_to_items______.rb
class AddOrderIdToItems < ActiveRecord::Migration
   def change
      add_column :items, :order_id, :integer
   end
end

$ rake db:migrate
#app/models/order.rb
class Order < ActiveRecord::Base
   has_many :items, inverse_of: :order
end

#app/models/item.rb
class Item < ActiveRecord::Base
   belongs_to :order, inverse_of: :items
   after_save :check_order, on: :update

   private

   def check_order
      items = Item.where(order_id: order.id).where.not(status: "shipped").count
      order.update(status: "complete") if items > 0
   end
end
@item = Item.find params[:id]
@item.update(status: "shipped") #-> "check_order" will happen, saving "order" as "complete" if all items are shipped
#app/models/order.rb
class Order < ActiveRecord::Base
   has_many :order_items
   has_many :items, through: :order_items
end

#app/models/order_item.rb
class OrderItem < ActiveRecord::Base
   #columns id | order_id | item_id | created_at | updated_at
   belongs_to :order
   belongs_to :item

   after_save :check_order, on: :update

   private

   def check_order
      items = Item.where(order_id: order.id).where.not(status: "shipped").count
      order.update(status: "complete") if items > 0
   end
end

#app/models/item.rb
class Item < ActiveRecord::Base
   has_many :order_items
   has_many :orders, through: :order_items
end
@order = Order.find params[:id]
@item = Item.find params[:id]

@order.items << @item #-> adds "item" to order 
@order = Order.find params[:id]

@item = @order.order_items.find x
@item.update status: "shipped"