Ruby on Rails:迭代关系或关联的最佳方式

时间:2017-10-21 23:06:53

标签: sql ruby-on-rails ruby database activerecord

我看到.where语句通过大量 CACHE用户加载消息而不是关联提出了如此多的请求。这是真的吗?

在这种情况下,我得到一个 ActiveRecord_Relation:

@dogs = Dog.where(user_id: current_user.id).order('created_at DESC')

在另一个案例中,我得到一个 ActiveRecord_Associations_CollectionProxy:

@dogs = current_user.dogs.order('created_at DESC')

当我在视图中进行迭代时

<% @dogs.each do |dog| %>
<div><%= dog.name %></div>
<% end %>

我在控制台日志中收到了不同的消息:

ActiveRecord_Relation:

User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]

ActiveRecord_Associations_CollectionProxy:

User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
Dog Load (0.6ms)  SELECT "dogs".* FROM "dogs" WHERE "dogs"."user_id" = ? ORDER BY "dogs"."created_at" DESC  [["user_id", 15]]

哪个更好?非常感谢你。

1 个答案:

答案 0 :(得分:4)

似乎在两种情况下current_user只应调用一次。据推测,current_user方法具有如下实现:

def current_user
  # read some cookies or something
  User.find_by([...])
end

我不清楚为什么{&1 34}会在&#34; ActiveRecord_Relation&#34;中多次调用User.find_by。版本,但似乎它必须是正在发生的事情。 Rails正在缓存此查询的结果,所以每次第一次点击热缓存后都会这样。

要排除这一点,您可以memoize #current_user。这应该可以防止在第一次调用current_user之后每个人都看到Active Record。