我使用Rails 5.我有这个模型
class MyObjectTime < ActiveRecord::Base
...
has_many :user_my_object_time_matches
然后在我的控制器中我有这个用于查询某些模型
@results = MyObjectTime.joins(:race,
"LEFT JOIN user_my_object_time_matches on my_object_times.id = user_my_object_time_matches.my_object_time_id #{additional_left_join_clause}")
.where( search_criteria.join(' and '), *search_values )
.limit(1000)
.order("my_objects.day DESC, my_objects.name")
.paginate(:page => params[:page])
.includes(:user_my_object_time_matches)
我的问题是,虽然我希望返回所有MyObjectTime对象,但根据某些条件,我不想要所有的&#34; user_my_object_time_objects&#34;附加到每个模型的只有满足某些标准的标准(例如,其user_my_object_time_match.user_id字段为空或等于&#34; 30&#34;的那些标准)。如何指定标准以仅强制为每个MyObjectTime模型包含某些user_my_object_time_matches?
答案 0 :(得分:0)
包含用于预先加载,因此我假设您需要加载MyObjectTime
个记录以及user_my_object_time_matches
个关联,因此您不必再查询数据库。
包含工作的方式是:
MyObjectTime.where(search_criteria.join(' and '))includes(:user_my_object_time_matches)
那将查询数据库两次:
根据search_criteria
加载所有MyObjectTime记录SELECT * FROM my_object_times WHERE (....)
加载所有关联的UserMyObjectTimeMachine
条记录
SELECT * FROM user_my_object_time_machines WHERE my_object_time_id IN ( [ids returned by the previous query ])
因此,如果您想在第二个查询中添加其他过滤,那么在模型MyObjectTime
中您可以添加另一个关联:
class MyObjectTime < ActiveRecord::Base
...
has_many :user_my_object_time_matches
has_many :user_my_object_time_matches_with_null_user, -> { where("user_id IS NULL or user_id = 30") }, class_name: "UserMyObjectMatch"
然后当你打电话
MyObjectTime.where(search_criteria.join(' and ')).includes(:user_my_object_time_matches_with_null_user)
第二个查询将如下所示:
SELECT * FROM user_my_object_time_machines WHERE (user_id IS NULL OR user_id = 30) AND my_object_time_id IN ( [ids returned by the previous query ])
这样你的例子就像这样:
@results = MyObjectTime.joins(:race)
.where( search_criteria.join(' and '), *search_values )
.limit(1000)
.order("my_objects.day DESC, my_objects.name")
.paginate(:page => params[:page])
.includes(:user_my_object_time_matches_with_null_user)
没有急切加载
如果每次条件不一样(user_id IS NULL或user_id = 30),那么我不知道一个好的方法来急切加载所有东西。所以你可以使用普通的左连接,但是当你试图获取关联记录时会执行查询:
@results = MyObjectTime.joins(:race,
"LEFT JOIN user_my_object_time_matches on my_object_times.id = user_my_object_time_matches.my_object_time_id AND (user_my_object_time_matches.user_id IS NULL or user_my_object_time_matches.user_id = 30)")
.where( search_criteria.join(' and '), *search_values )
.limit(1000)
.order("my_objects.day DESC, my_objects.name")
.paginate(:page => params[:page])
.includes(:user_my_object_time_matches)
您可以在渴望加载关联中找到大量文档:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html