Rails / ActiveRecord新手在这里。考虑以下用于课堂,用户和课堂注册的模型(在两者之间加入)
class Classroom < ActiveRecord::Base
has_many :fulltime_enrollments, -> { where(duration: 'full-time') }, class_name: "ClassroomEnrollments"
has_many :fulltimers, :through => :fulltime_enrollments, class_name: "User"
has_many :parttime_enrollments, -> { where(duration: 'part-time') }, class_name: "ClassroomEnrollments"
has_many :parttimers, :through => :parttime_enrollments, class_name: "User"
end
class ClassroomEnrollment < ActiveRecord::Base
# columns: user_id, classroom_id, duration
belongs_to :user
belongs_to :classroom
end
class User < ActiveRecord::Base
has_many :classroom_enrollments
has_many :classrooms, :through => :classroom_enrollments
end
教室和课堂教程的以下模型不起作用。当我尝试通过:fulltimers
或:parttimers
访问时,undefined method 'to_sym' for nil:NilClass
和my_classroom.fulltimers
别名会导致my_classroom.parttimers
错误。
如果我删除了:parttimers
别名并将:fulltimers
重命名为:users
,它可以正常工作(并且只显示全职学生),所以在我看来它有事情要做即使我在:fulltimers
条件中指定了User
,也可以确定classname: "User"
属于has_many
类型。
我做错了什么?
答案 0 :(得分:5)
由于无法自动推断源关联,因此您需要使用:source
选项指定它:
class Classroom < ActiveRecord::Base
has_many(
:fulltime_enrollments,
-> { where(duration: 'full-time') },
class_name: "ClassroomEnrollments"
)
has_many :fulltimers, :through => :fulltime_enrollments, :source => :user
has_many(
:parttime_enrollments,
-> { where(duration: 'part-time') },
class_name: "ClassroomEnrollments"
)
has_many :parttimers, :through => :parttime_enrollments, :source => :user
end
http://guides.rubyonrails.org/association_basics.html#options-for-has-many-source
尝试更清晰,更易读的方法怎么样?像这样:
class Classroom < ActiveRecord::Base
has_many :classroom_enrollments
has_many :users, through: :classroom_enrollments
def full_timers
users_by_duration("full-time")
end
def part_timers
users_by_duration("part-time")
end
private
def users_by_duration(duration)
users.where(classroom_enrollments: { duration: duration })
end
end
然后:
my_classroom = Classroom.find(1)
my_classroom.full_timers
答案 1 :(得分:1)
我在做类似的事情时偶然发现了这一点。这将生成相同的sql并且更容易查看。
class Classroom < ActiveRecord::Base
has_many :classroom_enrollments
has_many :users, through: :classroom_enrollments
def fulltimers
users.merge(ClassroomEnrollment.full_time)
end
def parttimers
users.merge(ClassroomEnrollment.part_time)
end
end
class ClassroomEnrollment < ActiveRecord::Base
belongs_to :user
belongs_to :classroom
scope :fulltime, ->{ where(duration: 'full-time') }
scope :parttime, ->{ where(duration: 'part-time') }
end
class User < ActiveRecord::Base
has_many :classroom_enrollments
has_many :classrooms, :through => :classroom_enrollments
end