我有一個應用程序,用戶可以在其中定製日曆並使用給定的事件池填充日曆。用戶也可以用別名覆蓋他自己日曆的標題。所以我有以下has_many:通過關係:Rails:如何在has_many:through關係中使用JOIN設置IF條件
class Calendar < ActiveRecord::Base
has_many :event_aliases
has_many :events, :through => :event_aliases
end
class Event < ActiveRecord::Base
attr_accessible :title
has_many :event_aliases
has_many :calendars, :through => :event_aliases
end
class EventAliases < ActiveRecord::Base
attr_accessible :course_id, :calendar_id, :custom_name
belongs_to :event
belongs_to :calendar
end
不,我想用別名來提供日曆。如果一個事件有一個別名(custom_name
),它應該顯示。否則,應顯示默認事件名稱(title
)。
有沒有辦法輕鬆設置查詢,返回當前日曆的所有事件,無論是使用custom_name
(如果存在)還是使用默認的title
?
我目前的解決方案是將if條件硬編碼到我想避免的查詢中。
title_column = "case when custom_name IS NOT NULL then custom_name else title end as title"
# assume we are given a calendar_id
Calendar.find(calendar_id).event_aliases.joins(:event).select(title_column, :event_id).each do |event_alias|
# do further stuff here
end
我還可以獲取所有event_aliases
,並通過他們每個人的運行,如果需要獲得默認title
。
# assume we are given a calendar_id
Calendar.find(calendar_id).event_aliases.each do |event_alias|
title = event_alias.custom_name
if title.nil?
title = Event.find(event_alias.event_id).title
# do further stuff here
end
但是,這一個會導致太多的查詢給我。
那麼有什麼更聰明的方式來完成我想要的?也許使用命名範圍或其他花式導軌技術?
UPDATE
我結束了做一個 「自定義」 通過的has_many選擇:通過關係。所以,唯一的變化是Calendar
型號:
class Calendar < ActiveRecord::Base
has_many :event_aliases
has_many :events, :through => :event_aliases,
:select => "event_aliases.custom_name as custom_name, events.*"
end
所以訪問custom_name
/的title
現在情況有點像@Doon建議:
Calendar.find(1).courses.each do |course|
title = course.custom_name || course.title
end
這就造成只有2查詢,而不是3:
Calendar Load (0.6ms) SELECT `calendars`.* FROM `calendars` WHERE `calendars`.`id` = 1 LIMIT 1
Event Load (0.7ms) SELECT event_aliases.custom_name as custom_name, events.* FROM `events` INNER JOIN `event_aliases` ON `events`.`id` = `event_aliases`.`event_id` WHERE `event_aliases`.`calendar_id` = 1
感謝您的提示。那麼'include()'解決方案與'joins()'解決方案沒有多大區別。在你的解決方案中,你只需在Ruby中而不是SQL中創建if條件。我想出了另一個受此影響的解決方案,但需要少一個查詢。 – LeEnno 2012-07-18 06:52:55