我的应用程序中有一个用户,该用户可以具有多个评估,计划和材料。我的数据库中这些之间已经存在关系。我想在一个选项卡中显示所有这些内容,而不必查询数据库太多次。
我试图做一个将它们全部合并到一个表中的方法,但是没有成功。返回是以下错误:undefined method 'joins' for #<User:0x007fcec9e91368>
def library
self.joins(:materials, :assessments, :plans)
end
我的最终目标是仅对联接返回的所有对象进行编程,以便可以显示它们,而不是需要查询三个不同的变量来减慢加载时间。知道这怎么可能吗?
class User < ApplicationRecord
has_many :materials, dependent: :destroy
has_many :plans, dependent: :destroy
has_many :assessments, dependent: :destroy
end
class Material < ApplicationRecord
belongs_to :user
end
class Assessment < ApplicationRecord
belongs_to :user
end
class Plan < ApplicationRecord
belongs_to :user
end
答案 0 :(得分:2)
如果您要做的只是预加载关联,请使用includes
:
class User < ApplicationRecord
# ...
scope :with_library, -> { includes(:materials, :assessments, :plans) }
end
像这样使用它:
User.with_library.find(1)
User.where(:name => "Trenton").with_library
User.all.with_library
# etc.
一旦关联被预加载,您可以将其用于library
方法,以使用特定用户的所有材料,评估和计划填充单个阵列:
class User < ApplicationRecord
# ...
def library
[materials, assessments, plans].map(&:to_a).flatten(1)
end
end
用例示例:
users = User.all.with_library
users.first.library
# => [ ... ]
更多信息:https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
答案 1 :(得分:0)
将includes
优先于joins
,除非您有其他特殊原因。 includes
将消除N + 1个查询,同时仍在关联中构造可用的记录:然后,您可以像以往那样遍历所有内容。
但是,在这种情况下,听起来好像您是在单个User
实例中工作:在这种情况下,includes
(或joins
)真的无济于事-没有N + 1个查询可以消除。
避免在您要显示的每行(N + 1)上运行查询很重要,但是一个查询和三个查询之间的差异可以忽略不计。 (尝试将所有内容压缩在一起会花费更多的开销。)对于这种用法,这是不必要的。