I have this
class Student
has_many :assignments
end
class Assignment
belongs_to :student
belongs_to :book
end
class Book
has_many :assignments
end
To find the student's "Harry Potter" assignment, I am doing this
@student.assignments.find_by_book_id(Book.find_by_name('Harry Potter'))
Is there a way to make this into a has_one association for the Student
model?
Something like this (pseudo-code here)
class Student
has_many :assignments
has_one :harry_potter_assigment, -> { where book_id: Book.find_by_name('Harry Potter') }, class: 'Assignment'
end
If not with a has_one
, what is a better way?
If I'm not wrong, the following should work
#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
You can try to define it like this:
class Student < ActiveRecord::Base
has_many :assignments
def assignments_named(book_name)
self.assignments.join(:book).where("books.name=?",name)
end
end
Now querying:
student = Student.first
student.assignments_named('Harry Potter')
produces the following SQL:
SELECT "assignments".* FROM "assignments"
INNER JOIN "books" ON "books"."id" = "assignments"."book_id"
WHERE "assignments"."student_id" = 1 AND (books.name='Harry Potter')
It's not has_one
relation though. There might be zero, one or more assignments for given student and book 'Harry Potter'.
If you want to make book's title dynamic, you can do the following:
class Student
has_many :assignments
has_many :books, through: :assignments
def book_by_name(book_name)
books.find_by!(name: book_name)
end
end
And call it this way:
ron = Student.find_by(name: 'Ron')
harry_potter_book = ron.book_by_name('Harry Potter')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.