Ruby on rails rails activerecord关系联接表
我有一个国家模型和一个旅行笔记模型。一个国家有许多游记,而一张游记属于一个国家Ruby on rails rails activerecord关系联接表,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我有一个国家模型和一个旅行笔记模型。一个国家有许多游记,而一张游记属于一个国家 class TravelNote < ActiveRecord::Base default_scope { order(created_at: :desc) } belongs_to :country has_many :chapters before_destroy { draft? } validate :validates_uniqueness_of_draft, on:
class TravelNote < ActiveRecord::Base
default_scope { order(created_at: :desc) }
belongs_to :country
has_many :chapters
before_destroy { draft? }
validate :validates_uniqueness_of_draft, on: :create
enum status: { draft: 0, published: 1, archived: 2 }
enum advice_against: { no: 0, general: 1, tourists: 2 }
scope :country, ->(country_id) { where(country_id: country_id) }
# further methods omitted...
end
class Country < ActiveRecord::Base
default_scope { order(:iso_code) }
has_many :travel_notes
end
出于性能原因,我想删除TravelNote.published.country(country.id).first.try:published\u at,这样就不再有数百个数据库查询,而只剩下一个等效sql查询的数组:
select * from countries
left join travel_notes
on countries.id=travel_notes.country_id
如何实现它?您可以编写一个自定义范围,只包含已发布的注释 差不多
scope :include_published, -> { proc do |_|
joins("LEFT OUTER JOIN (
SELECT b.*
FROM travel_notes b
WHERE published = 1
GROUP BY b.country_id
) notes_select ON notes_select.country_id = countries.id"
).select("countries.*").select("#{insert what attributes you want to include }")
end.call(self, counted_model) }
您必须在第二个select子句中包含希望从注释中获得的属性,然后这些属性将作为同名方法包含在国家/地区活动记录结果中
SQL查询可以写得更漂亮,我只是拼凑了一些东西
我在我的项目中使用了类似的技术,但为了包括相关对象的计数。显然,您正在尝试加载与国家相关的“旅行笔记”:
Country.includes(:travel_notes).where(travel_notes: { status: 1} )
因此,您的代码将是:
我不确定,但你能试试
TravelNote.published.joins(:country).where(:countries=>{:id=>country.id}).map(&:published_at)
如果它能帮助汉克斯·桑蒂亚,那确实是有帮助的。除非我遗漏了什么,否则你不需要proc
在那里。关于proc可能是正确的,评论。我们有一个proc,因为我们将它提取到一个模块中,该模块根据所涉及的模型生成查询。非常感谢Albin Svensson。这很好,在另一种情况下,我肯定会使用您的方法,但在本例中,MohamedDia27的代码看起来更简单。
scope :include_published, -> { proc do |_|
joins("LEFT OUTER JOIN (
SELECT b.*
FROM travel_notes b
WHERE published = 1
GROUP BY b.country_id
) notes_select ON notes_select.country_id = countries.id"
).select("countries.*").select("#{insert what attributes you want to include }")
end.call(self, counted_model) }
Country.includes(:travel_notes).where(travel_notes: { status: 1} )
class CountriesController < ApplicationController
def index
@countries = Country.includes(:travel_notes).where(travel_notes: { status: 1} )
end
# rest of the class omitted...
end
@countries.each do |country|
%tr
%td= link_to country.name_de, country_travel_notes_path(country)
%td= country.travel_notes.first.published_at