我希望有一个简单的解决方案,不涉及find_by_sql,如果没有,那么我想这将不得不工作。
我发现这篇文章引用了这个:
Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })
哪个是一样的
SELECT * FROM topics WHERE forum_id IN (<@forum ids>)
我想知道是否有一种方法可以不这样做,比如:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
你可以尝试这样做:
Topic.find(:all, :conditions => ['forum_id not in (?)', @forums.map(&:id)])
你可能需要执行@forums.map(&:id).join(',')。如果参数是可枚举的,我不记得Rails是否会将参数放入CSV列表。
你也可以这样做:
# in topic.rb
named_scope :not_in_forums, lambda { |forums| { :conditions => ['forum_id not in (?)', forums.select(&:id).join(',')] }
# in your controller
Topic.not_in_forums(@forums)
使用服装:
topics=Topic.arel_table
Topic.where(topics[:forum_id].not_in(@forum_ids))
或者,如果喜欢的话:
topics=Topic.arel_table
Topic.where(topics[:forum_id].in(@forum_ids).not)
由于rails在:
topics=Topic.arel_table
Topic.where.not(topics[:forum_id].in(@forum_ids))
请注意,最终你不希望forum_ids是ids列表,而是一个子查询,如果是这样,那么你应该在获得主题之前做这样的事情:
@forum_ids = Forum.where(/*whatever conditions are desirable*/).select(:id)
通过这种方式,您可以在一个查询中获得所有内容:类似于:
select * from topic
where forum_id in (select id
from forum
where /*whatever conditions are desirable*/)
还要注意,最终您并不想这样做,而是想要一个连接——这可能更有效。
你可能想看看Ernie Miller的meta_where插件。你的SQL语句:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
...可以这样表示:
Topic.where(:forum_id.nin => @forum_ids)
Railscasts的Ryan Bates制作了一个很好的视频来解释MetaWhere。
不确定这是否是你想要的,但在我看来,它肯定比嵌入式SQL查询更好。
导轨 4+:
Article.where.not(title: ['Rails 3', 'Rails 5'])
Rails 3:
Topic.where('id NOT IN (?)', Array.wrap(actions))
其中actions是一个数组,包含:[1,2,3,4,5]
下面是一个更复杂的“not in”查询,使用rails 4中使用squeel的子查询。当然,与等效的sql相比非常慢,但是,嘿,它是有效的。
scope :translations_not_in_english, ->(calmapp_version_id, language_iso_code){
join_to_cavs_tls_arr(calmapp_version_id).
joins_to_tl_arr.
where{ tl1.iso_code == 'en' }.
where{ cavtl1.calmapp_version_id == my{calmapp_version_id}}.
where{ dot_key_code << (Translation.
join_to_cavs_tls_arr(calmapp_version_id).
joins_to_tl_arr.
where{ tl1.iso_code == my{language_iso_code} }.
select{ "dot_key_code" }.all)}
}
作用域中的前两个方法是声明别名cavtl1和tl1的其他作用域。<<是squeel中的not in操作符。
希望这能帮助到一些人。