我想知道我们是否可以在模型级别中加载:
# country.rb
class Country < ActiveRecord::Base
has_many :country_days
def country_highlights
country_days.map { |country_day| country_day.shops }.flatten.uniq.map { |shop| shop.name }.join(", ")
end
end
# country_day.rb
class CountryDay < ActiveRecord::Base
belongs_to :country
has_many :country_day_shops
has_many :shops, :through => :country_day_shops
end
# shop.rb
class Shop < ActiveRecord::Base
end
由于某些多态关联,大多数时候在控制器中使用.includes
很困难。无论如何,我是否急于在模型级别加载方法country_highlights
,这样我就不必在控制器中添加.includes
了?
答案 0 :(得分:2)
您不能从模型实例“急切加载”country_days,但您当然可以使用has_many through:
跳过将它们全部加载到一起。您也可以跳过额外的地图。
# country.rb
class Country < ActiveRecord::Base
has_many :country_days
has_many :country_day_shops, through: :country_days #EDIT: You may have to add this relationship
has_many :shops, through: :country_day_shops #And change this one to use the new relationship above.
def country_highlights
shops.distinct_names.join(", ")
end
end
# country_day.rb
class CountryDay < ActiveRecord::Base
belongs_to :country
has_many :country_day_shops
has_many :shops, :through => :country_day_shops
end
# shop.rb
class Shop < ActiveRecord::Base
def self.distinct_names
pluck("DISTINCT shops.name") #Edit 2: You may need this instead of 'DISTINCT name' if you get an ambiguous column name error.
end
end
has_many through:
将使用JOIN
加载关联商店记录,实际上是急切加载它们,而不是加载所有country_day记录,然后为每个country_day记录加载相关商店。
pluck("DISTINCT name")
将返回数据库中所有商店唯一名称的数组,使用数据库执行SELECT DISTINCT
,因此它不会返回重复记录,{{1}当您需要的只是字符串pluck
时,将避免加载ActiveRecord实例。
答案 1 :(得分:1)
编辑:首先阅读评论
您可以缓存最终结果(在您的情况下加入的字符串或文本记录),因此您不必加载几个级别的记录来构建此结果。
1)添加country_highlights
文本列(结果可能超出字符串列限制)
2)使用回调缓存模型中的country_highlights
,例如在每次保存之前。
class Country < ActiveRecord::Base
has_many :country_days
before_save :cache_country_highlights
private
def cache_country_highlights
self.country_highlights = country_days.flat_map(&:shops).uniq.map(&:name).join(", ")
end
end
缓存计算会在保存记录时调用一些开销,但是只需要加载一个而不是三个模型记录进行显示,这样可以加快控制器的操作速度,这是值得的。