Rails ActiveRecord SQL查询乱序

时间:2022-10-08 09:50:06

I'm implementing a sync method in my rails app, but my SQL queries are being executed in the wrong order, messing up the sync.

我正在我的rails应用程序中实现一个同步方法,但我的SQL查询正在以错误的顺序执行,弄乱了同步。

Basically, I'm sending new objects from the client app along with a timestamp of the last sync, then fetching anything that changed on the server since the timestamp. I then create the new objects from the client and save the timestamp after the new objects are created to exclude them from the next sync.

基本上,我从客户端应用程序发送新对象以及上次同步的时间戳,然后从时间戳中获取服务器上发生更改的任何内容。然后,我从客户端创建新对象,并在创建新对象后保存时间戳,以将它们从下一次同步中排除。

def sync(new_obj_hashes, last_sync)
  updated_items = Item.where(user_id: user_id).where("updated_at > ?", last_sync)

  new_obj_hashes.each |obj_hash|
    Item.new(obj_hash).save!
  end

  last_sync = Time.now
end

The problem: From my SQL logs

问题:来自我的SQL日志

UPDATE "items" SET ...blah blah... WHERE "items"."id" = x
SELECT "items".* FROM "items" WHERE "items"."user_id" = y AND (updated_at > z)

It's creating the new objects first and then fetching the updated objects, which means updated_items (which I send back to the client app) contains all the objects the client sent as well.

它首先创建新对象,然后获取更新的对象,这意味着updated_items(我发送回客户端应用程序)包含客户端发送的所有对象。

How do I get the SELECT statement to happen before the UPDATE?

如何在UPDATE之前获取SELECT语句?

1 个解决方案

#1


1  

updated_items = Item.where(user_id: user_id).where("updated_at > ?", last_sync)

doesn't execute a SQL statement. It creates an ActiveRecord::Relation object which will execute itself when you call a method on it requiring this (for example all or most methods from Enumerable.

不执行SQL语句。它创建一个ActiveRecord :: Relation对象,当你调用一个需要它的方法时它将自己执行(例如Enumerable中的所有或大多数方法)。

In your case sounds like you want to do

在你的情况下听起来像你想做的

updated_items = Item.where(user_id: user_id).where("updated_at > ?", last_sync).all

so that the query is evaluated then rather than when you next use updated_items

这样就可以评估查询,而不是下次使用updated_items时

#1


1  

updated_items = Item.where(user_id: user_id).where("updated_at > ?", last_sync)

doesn't execute a SQL statement. It creates an ActiveRecord::Relation object which will execute itself when you call a method on it requiring this (for example all or most methods from Enumerable.

不执行SQL语句。它创建一个ActiveRecord :: Relation对象,当你调用一个需要它的方法时它将自己执行(例如Enumerable中的所有或大多数方法)。

In your case sounds like you want to do

在你的情况下听起来像你想做的

updated_items = Item.where(user_id: user_id).where("updated_at > ?", last_sync).all

so that the query is evaluated then rather than when you next use updated_items

这样就可以评估查询,而不是下次使用updated_items时