has_many :throughなリレーションで中間テーブルをみつついい感じに絞り込みたい
これまで新しめのアプリではMongoを使ってたんですが、近頃になってようやくActiveRecordをproductionでもりもり使っています。Arelいいですね。
で、本題。こういう場合に、attendances.statusを見てeventsを絞り込みたい。これをかっこよく書くにはどうすればいいか。
class Person < ActiveRecord::Base has_many :attendances has_many :events, through: :attendances end class Attendance < ActiveRecord::Base belongs_to :people belongs_to :events # t.string :status STATUSES = %w[registered paid canceled attended absented].freeze validates_inclusion_of :status, in: STATUSES end class Event < ActiveRecord::Base end
で、いまの解。もうちょっとかっこいいのはないかしら。
class Person < ActiveRecord::Base has_many :attendances has_many :events, through: :attendances do Attendance::STATUSES.each do |stat| class_eval %(def #{stat}; stats(#{stat.dump}); end) end def stats(*stats) where("#{Attendance.quoted_table_name}.status IN ?", stats) end end end # => person.events.canceled # => person.events.paid
Event側からstatusごとに数えるときは、実用性に寄せればビューをつくってクロス集計かなぁ。
幸いにしてそうしたくらいで問題になるようなパフォーマンス要件ではないし。