Сохранение модели активной записи меняет свой запрос отношения? - PullRequest
0 голосов
/ 23 марта 2020

Вот часть класса:

...
   def sale_to_fulfill_purchase
     p Sale.where(fulfilled: false).order(for_sale_at: :asc).limit(1).offset(@sale_number).to_sql
     Sale.where(fulfilled: false).order(for_sale_at: :asc).limit(1).offset(@sale_number).first
   end

   def need_one_more_sale
     @sale_number += 1
   end

   def fill_sales_with_new_purchase!
     ActiveRecord::Base.transaction do
       until purchase_filled_with_sales?
          sale  = sale_to_fulfill_purchase
          p sale
          value = value_from_sale_to_purchase(sale)

          purchase .purchase_value(value)
          sale     .sell_value(value)
          PurchaseOfSale.create!(purchased_at: Time.current,
                                 purchase: purchase,
                                 sale: sale,
                                 amount: value)
          sale.save!
          need_one_more_sale
        end
        purchase.save!
      end
    end
...

Есть и другие методы, но я не думаю, что они важны. Нет активных обратных вызовов записей.

Вывод не соответствует ожидаемому:

"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 0"
#<Sale id: 1, initial_value: 5, remaining_value: 5, fulfilled: false, admin_id: 1, for_sale_at: "2020-03-20 00:05:52", user_id: nil, created_at: "2020-03-23 00:05:52", updated_at: "2020-03-23 00:05:52", purchase_id: nil>
"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 1"
#<Sale id: 3, initial_value: 3, remaining_value: 3, fulfilled: false, admin_id: 3, for_sale_at: "2020-03-22 00:05:52", user_id: nil, created_at: "2020-03-23 00:05:52", updated_at: "2020-03-23 00:05:52", purchase_id: nil>
"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 2"

Если я закомментирую строку sale.save!, мой вывод соответствует ожидаемому:

"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 0"
#<Sale id: 1, initial_value: 5, remaining_value: 5, fulfilled: false, admin_id: 1, for_sale_at: "2020-03-20 00:10:06", user_id: nil, created_at: "2020-03-23 00:10:06", updated_at: "2020-03-23 00:10:06", purchase_id: nil>
"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 1"
#<Sale id: 2, initial_value: 4, remaining_value: 4, fulfilled: false, admin_id: 2, for_sale_at: "2020-03-21 00:10:06", user_id: nil, created_at: "2020-03-23 00:10:06", updated_at: "2020-03-23 00:10:06", purchase_id: nil>
"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 2"
#<Sale id: 3, initial_value: 3, remaining_value: 3, fulfilled: false, admin_id: 3, for_sale_at: "2020-03-22 00:10:06", user_id: nil, created_at: "2020-03-23 00:10:06", updated_at: "2020-03-23 00:10:06", purchase_id: nil>
"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 3"

Я также заметил, что если я изменю код класса:

def sale_to_fulfill_purchase
  p Sale.where(fulfilled: false).order(for_sale_at: :asc).limit(1).offset(@sale_number).to_sql
  Sale.where(fulfilled: false).order(for_sale_at: :asc).limit(1).offset(@sale_number)

end

def fill_sales_with_new_purchase!
  ActiveRecord::Base.transaction do
    until purchase_filled_with_sales?

      sale  = sale_to_fulfill_purchase.first
      p sale
      value = value_from_sale_to_purchase(sale)
      # p value

      purchase .purchase_value(value)
      sale     .sell_value(value)
      PurchaseOfSale.create!(purchased_at: Time.current,
                             purchase: purchase,
                             sale: sale,
                             amount: value)
      sale.save!
      # need_one_more_sale
    end
    purchase.save!
  end
end

Обратите внимание, что я возвращаю отношение, а не первый объект, я прекращаю изменять смещение для запроса, но теперь я снова звоню sale.save!.

Это дает мне правильный вывод:

"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 0"
#<Sale id: 1, initial_value: 5, remaining_value: 5, fulfilled: false, admin_id: 1, for_sale_at: "2020-03-20 00:21:32", user_id: nil, created_at: "2020-03-23 00:21:32", updated_at: "2020-03-23 00:21:32", purchase_id: nil>
"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 0"
#<Sale id: 2, initial_value: 4, remaining_value: 4, fulfilled: false, admin_id: 2, for_sale_at: "2020-03-21 00:21:32", user_id: nil, created_at: "2020-03-23 00:21:32", updated_at: "2020-03-23 00:21:32", purchase_id: nil>
"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 0"
#<Sale id: 3, initial_value: 3, remaining_value: 3, fulfilled: false, admin_id: 3, for_sale_at: "2020-03-22 00:21:32", user_id: nil, created_at: "2020-03-23 00:21:32", updated_at: "2020-03-23 00:21:32", purchase_id: nil>
"SELECT \"sales\".* FROM \"sales\" WHERE \"sales\".\"fulfilled\" = FALSE ORDER BY \"sales\".\"for_sale_at\" ASC LIMIT 1 OFFSET 0"

Любой совет, почему я получаю этот неинтуитивный вывод?

...