2015-11-01 2 views
0

У меня есть 2 модели - заказ и позиция:Обновить родительский объект, когда дочерние объекты отвечают определенному условию

order.rb:

class Order < ActiveRecord::Base 
    has_many :items 
end 

item.rb:

class Item < ActiveRecord::Base 
belongs_to :order 
end 

схемы для элемента :

t.decimal "price",  precision: 12, scale: 3 
t.string "status" 

схема для заказываются:

t.string "status" 

Состояние предмета будет помечено как отправленное при получении пользователем предметов. Итак, как я могу обновить статус заказа до «завершения», при условии, что статус всех элементов обновлен до «отправлен»?

ответ

0

Вам необходимо обновить items таблицу включить foreign key, связывая его с orders:

$ 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 

Вы можете узнать больше о том, почему это важно here:

enter image description here

-

Это позволит вам сделать следующее: мычание:

#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 

Реальный исправить это, чтобы создать has_many :through отношения, чтобы связать многие Items многим Orders. Таким образом, вы можете пометить каждый из OrderItems как «отправлен»:

#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 

Вам нужно только ввести OrderItem модель (изменения в Item и Order модели не нужны):

enter image description here

Это позволит вам сделать следующее:

@order = Order.find params[:id] 
@item = Item.find params[:id] 

@order.items << @item #-> adds "item" to order 

вы тогда быть BLE использовать следующие параметры для того, как заказ был «завершен» или нет:

@order = Order.find params[:id] 

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

я бы что-то вроде этого:

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 

А затем вызвать item.complete_order каждый раз когда Item отмечен как shipped.

+0

Где я должен позвонить 'item.complete_order' или я должен использовать обратные вызовы, как after_update?И что, если я получил еще одно условие, что статус элемента = «возврат», поэтому, если 2 предмета отправлены, а 1 элемент - «возврат», статус заказа должен быть отмечен как «неполный». Благодарю. – pyfl88

+0

Вы сказали: * Статус предмета будет помечен как отправленный, когда пользователь получил предметы *, поэтому вы вызываете 'item.complete_order' в тот же момент/место, где статус элемента обновляется. По второму вопросу я бы добавил его в тело вопроса, так как это на самом деле еще одна особенность. Аналогичным образом вы бы реплицировали логику для обработки этого случая. – dgilperez

Смежные вопросы