У меня есть приложение электронной коммерции, которое демонстрирует странное поведение. Продукт представляет собой учебный класс. Студент создает резервирование для различных классов, которые добавляются в корзину в качестве отдельных позиций. В какой-то момент и заказ создан и оплачен, после чего мне нужно выполнить итерацию по каждому из резервирований и обновить атрибут «заплатил». Итак, вот строение базы данных ...
1) Class has_many Reservations
2) Reservation belongs_to class, and has_one line_item (and has a decimal :paid attribute)
3) Line_item belongs_to reservation, and belongs_to cart
4) Cart has_many line_items, and has_one order
Итак, когда студент создает заказ, выполняется транзакция по кредитной карте, и в случае успеха я хочу сгенерировать и отправить по электронной почте квитанцию студенту.
Изначально в моем методе OrdersController # метод создания выглядел примерно так ...
def create
@cart = current_cart #retrieves the cart
@order = @cart.build_order(params[:order])
# snip saving order and purchase transaction
# I would then iterate over the line-items with
@cart.line_items.each { |li| li.reservation.update_attribute(:paid, li.reservation.fee)}
Однако в этот момент я обнаружил, что значение атрибута paid будет зависеть от того, как был получен доступ к line_item. Если бы я получил доступ через ...
@cart.line_items.each {|li| li.reservation.paid }
значения будут такими, как установлено. ОДНАКО, если бы он использовал ...
@order.cart.line_items.each {|li| li.reservation.paid }
Значение будет равно нулю. (Но это был доступ к правильному резервированию. Идентификатор)
Затем я обнаружил, что если я изменил строку, в которой установлен атрибут оплачиваемого, на следующий ...
@order.cart.line_items.each { |li| li.reservation.update_attribute(:paid, li.reservation.fee)}
что любой из вышеперечисленных обращений вернул бы правильное значение.
Так что я думаю, мой вопрос, в чем разница при установке атрибута: paid с
@cart.line_items.each ...
и
@order.cart.line_times.each ...
На основании приведенного ниже комментария я переместил итерацию в модель корзины. теперь оно имеет
def paid_deposit!
self.line_items.includes(:reservation).each do |li|
li.reservation.update_attribute(:paid, li.reservation.deposit)
end
end
Однако такая же проблема существует
Контроллер имеет следующий код ...
@cart.paid_deposit!
@cart.line_items.each {|li| logger.debug "Cart: Res: #{li.reservation.id}, Paid: #{li.reservation.paid}" }
@order.cart.line_items.each {|li| logger.debug "Order: Res: #{li.reservation.id}, Paid: #{li.reservation.paid}" }
В результате получается лог ...
Reservation Load (0.3ms) SELECT `reservations`.* FROM `reservations` WHERE `reservations`.`id` IN (346, 347, 348)
(0.2ms) BEGIN
(0.2ms) UPDATE `reservations` SET `paid` = 40.0, `updated_at` = '2012-02-05 22:12:36' WHERE `reservations`.`id` = 346
(0.4ms) COMMIT
(0.1ms) BEGIN
(0.1ms) UPDATE `reservations` SET `paid` = 40.0, `updated_at` = '2012-02-05 22:12:36' WHERE `reservations`.`id` = 347
(0.6ms) COMMIT
(0.1ms) BEGIN
(0.1ms) UPDATE `reservations` SET `paid` = 25.0, `updated_at` = '2012-02-05 22:12:36' WHERE `reservations`.`id` = 348
(0.3ms) COMMIT
LineItem Load (0.1ms) SELECT `line_items`.* FROM `line_items` WHERE `line_items`.`cart_id` = 24
Reservation Load (0.2ms) SELECT `reservations`.* FROM `reservations` WHERE `reservations`.`id` = 346 LIMIT 1
Cart: Res: 346, Paid: 40.0
Reservation Load (0.1ms) SELECT `reservations`.* FROM `reservations` WHERE `reservations`.`id` = 347 LIMIT 1
Cart: Res: 347, Paid: 40.0
Reservation Load (0.1ms) SELECT `reservations`.* FROM `reservations` WHERE `reservations`.`id` = 348 LIMIT 1
Cart: Res: 348, Paid: 25.0
Order: Res: 346, Paid: 0.0
Order: Res: 347, Paid: 0.0
Order: Res: 348, Paid: 0.0
Как видно, ссылка на оплаченную сумму из корзины получает правильные значения, а то же самое из Заказа - нет. Видимо, используя кэшированные значения? Нет доступа к базе данных.