【问题标题】:How should I use scope in Rails 3?我应该如何在 Rails 3 中使用范围?
【发布时间】:2011-11-20 22:49:36
【问题描述】:
我有两个模型:
第一:
class CountryList < ActiveRecord::Base
has_one :country, :dependent => :nullify
end
第二:
class Country < ActiveRecord::Base
belongs_to :country_list
end
我需要在 CountryList 模型中创建一个范围,其中将包含所有与国家无关的记录。
像这样的:
CountryList.all.each do |country_list|
country_list.country.nil?
end
【问题讨论】:
标签:
ruby-on-rails
scope
associations
relational-database
【解决方案1】:
你可以这样做:
class CountryList < ActiveRecord::Base
def self.without_countries
joins(:country).
select("country_lists.*, COUNT(countries.id) AS country_count").
group("country_lists.id").
having("country_count = 0")
end
end
但请注意,这可能不是西方最快的查询。
更好的方法是使用 ActiveRecord counter_cache,但这需要一个额外的列,并且是一种非规范化,您可以找到详细信息 here。 counter_cache 绝对是一个更快的战利品,如果你不退出 ActiveRecord,即你不使用原始 SQL 操作你的数据库从而绕过你的 ActiveRecord ORM,反规范化不会伤害你。
顺便说一句。我假设你的意思是
CountryList.all.select do |country_list|
country_list.countries.empty?
end
【解决方案2】:
我这里没有终端,但是:
class CountryList < ActiveRecord::Base
scope :no_country, joins('LEFT OUTER JOIN countries ON (country_list_id = #{id})').where(:countries => {:country_id => nil})
end
我很确定 #{id} 部分会给你一个警告,但我不记得 R3 中的正确语法。
【解决方案3】:
class CountryList < ActiveRecord::Base
has_one :country, :dependent => :nullify
scope :countryless, where(:country_id => nil)
end
CountryList.countryless.all