ユーザーがカレンダーをカスタマイズして、特定のイベントのプールを入力できるアプリケーションがあります。ユーザーは自分のカレンダーのタイトルを別名で上書きすることもできます。したがって、次の has_many :through リレーションがあります。
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
しかし、これではクエリが多すぎます。
それで、私が望むものを達成するためのよりスマートな方法はありますか? たぶん、名前付きスコープまたは別の派手なレール技術を使用していますか?
アップデート
has_many :through 関係を介して「カスタム」選択を行うことになりました。したがって、唯一の変更点は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
これにより、3 つではなく 2 つのクエリのみが作成されます。
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