ActiveRecord has_one具有动态范围

时间:2015-09-15 05:46:05

标签: ruby-on-rails activerecord

我有这个

class Student
  has_many :assignments
end

class Assignment
  belongs_to :student
  belongs_to :book
end

class Book
  has_many :assignments
end

为了找到学生的“哈利波特”作业,我正在做这个

@student.assignments.find_by_book_id(Book.find_by_name('Harry Potter'))

有没有办法让它成为Student模型的has_one关联?

像这样的东西(这里是伪代码)

class Student
  has_many :assignments
  has_one  :harry_potter_assigment, -> { where book_id: Book.find_by_name('Harry Potter') }, class: 'Assignment'
end

如果没有has_one,那么更好的方法是什么?

3 个答案:

答案 0 :(得分:2)

如果我没错,以下内容应该有效

#student.rb
class Student
  has_many :assignments
  has_one :harry_potter_assigment, -> { where(book_id: Book.find_by_name('Harry Potter').id }, class_name: "Assignment"
end

答案 1 :(得分:1)

您可以尝试像这样定义:

class Student < ActiveRecord::Base
  has_many :assignments

  def assignments_named(book_name)
    self.assignments.join(:book).where("books.name=?",name)
  end
end

现在查询:

student = Student.first
student.assignments_named('Harry Potter')

生成以下SQL:

SELECT "assignments".* FROM "assignments"
INNER JOIN "books" ON "books"."id" = "assignments"."book_id"
WHERE "assignments"."student_id" = 1 AND (books.name='Harry Potter')

但它不是has_one关系。对于给定的学生和书籍“哈利波特”,可能会有零个,一个或多个作业。

答案 2 :(得分:0)

如果您想让图书的标题动态化,您可以执行以下操作:

class Student
  has_many :assignments
  has_many :books, through: :assignments

  def book_by_name(book_name)
    books.find_by!(name: book_name)
  end
end

并以这种方式称呼它:

ron = Student.find_by(name: 'Ron')
harry_potter_book = ron.book_by_name('Harry Potter')