我有三种模型,用户,注册人,程序。
注册人是用户和程序之间的联接表,包含user_id
,program_id
和status
,这是一个枚举。
class User < ApplicationRecord
has_many :registrants, dependent: :destroy
has_many :programs, through: :registrants
end
class Registrant < ApplicationRecord
belongs_to :user
belongs_to :program
enum status: {
enrolled: 1,
unenrolled: 2,
instructor: 3,
passed: 4,
failed: 5
}
scope :active, -> { where(status: [:enrolled, :instructor]) }
end
class Program < ApplicationRecord
has_many :registrants, dependent: :destroy
has_many :users, through: :registrants
end
我希望只能从连接表中检索枚举状态为:enrolled或:instructor的记录,以便我可以执行以下操作:
program.registrants.active.users
我该如何完成?
由于program.registrants.active.users
,应避免使用像Law of Demeter这样的长链,所以这不是一个好目标。
您可以通过传递哈希将条件添加到.where
中的联接表:
program.users.where(
registrants: { status: [:enrolled, :instructor] }
)
请注意,键应该是表名(或其在查询中的别名),而不是关联的名称。
您还可以传递范围:
program.users.where(Registrant.active)
您还可以通过创建“作用域”关联来清理此问题:
class Program < ApplicationRecord
has_many :registrants, dependent: :destroy
has_many :users, through: :registrants
has_many :active_users,
through: :registrants,
source: :user,
-> { where(Registrant.active) }
end
谁会让您打电话:
program.active_users # Demeter is happy.