我正在使用Rails 4.1,并且有一个非常基本的问题,即急于加载工作。
我已将一个复杂的程序简化为事件,用户和预订的一个非常基本的例子:
event
型号:
class Event < ActiveRecord::Base
has_many :reservations
def reserved?(user)
reservations.where(user: user).present?
end
end
user
型号:
class User < ActiveRecord::Base
has_many :reservations
end
reservation
型号:
class Reservation < ActiveRecord::Base
belongs_to :user
belongs_to :event
end
我的event controller
:
def index
@events = Event.includes(:reservations).all
@user = User.find(1)
end
我的views/events/index.html.erb
观点:
<% @events.each do |event| %>
<p>Event: <%= event.name %><br>
Reserved?: <%= event.reserved?(@user) %><br></p>
<% end %>
我创建了一个用户和三个事件。事件索引页的结果server log
:
Started GET "/events" for 127.0.0.1 at 2014-12-03 11:26:20 +0800
Processing by EventsController#index as HTML
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Event Load (0.1ms) SELECT "events".* FROM "events"
Reservation Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."event_id" IN (1, 2, 3)
Reservation Load (0.1ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."event_id" = ? AND "reservations"."user_id" = 1 [["event_id", 1]]
Reservation Load (0.0ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."event_id" = ? AND "reservations"."user_id" = 1 [["event_id", 2]]
Reservation Load (0.1ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."event_id" = ? AND "reservations"."user_id" = 1 [["event_id", 3]]
Rendered events/index.html.erb within layouts/application (10.0ms)
Completed 200 OK in 76ms (Views: 68.7ms | ActiveRecord: 1.3ms)
正如您所看到的,rails正确地加载了我的事件的所有预订。但是,它会在reserved?(user)
调用期间再次查询数据库。我究竟做错了什么?感谢。
答案 0 :(得分:2)
您的reserved?
方法使用where
关联的reservations
方法。 where
方法是一种用于构建SQL查询的ARel方法。对present?
方法的结果调用where
会导致执行查询。
为了避免在reserved?
中进行另一次数据库查找,您应该使用Ruby集合方法,例如:
def reserved?(user)
reservations.select { |reservation| reservation.user == user }.empty?
end
或者,对于更简洁的版本(有人将其添加为评论,但看起来它可能已被删除):
def reserved?(user)
reservations.map(&:user_id).include?(user.id)
end