我有users表,books表和books_users连接表。在users_controller.rb中,我尝试提取具有filtered_books的用户。请帮助我解决该问题。
user.rb
has_many :books_users, dependent: :destroy
has_and_belongs_to_many :books, join_table: :books_users
book.rb
has_and_belongs_to_many :users
books_user.rb
belongs_to :user
belongs_to :book
users_controller.rb
def filter_users
@filtered_books = Fiction.find(params[:ID]).books
@users = **I want only those users who have filtered_books**
end
has_and_belongs_to_many
实际上并不使用联接模型。您正在寻找的是has_many through:
class User < ApplicationRecord
has_many :book_users
has_many :books, through: :book_users
end
class Book < ApplicationRecord
has_many :book_users
has_many :users, through: :book_users
end
class BookUser < ApplicationRecord
belongs_to :book
belongs_to :user
end
如果要向书籍添加类别,则可以通过添加类别模型和另一个联接表来完成。如果要创建多个类别,则不能通过创建Fiction
模型来创建大量重复的代码。
class Book < ApplicationRecord
has_many :book_users
has_many :users, through: :book_users
has_many :book_categories
has_many :categories, through: :book_categories
end
class BookCategory < ApplicationRecord
belongs_to :book
belongs_to :category
end
class Category < ApplicationRecord
has_many :book_categories
has_many :books, through: :book_categories
end
如果您要查询遵循特定书籍的用户,则可以使用内部连接并在书籍上附加条件来做到这一点:
User.joins(:books)
.where(books: { title: 'Lord Of The Rings' })
如果您要获取具有特定类别的图书:
Book.joins(:categories)
.where(categories: { name: 'Fiction' })
然后进行大结局-要查询与至少一本归类为“小说”的书籍有关联的用户,您应该这样做:
User.joins(books: :categories)
.where(categories: { name: 'Fiction' })
# or if you have an id
User.joins(books: :categories)
.where(categories: { id: params[:category_id] })
您还可以添加一个间接关联,使您可以直接从类别转到用户:
class Category < ApplicationRecord
# ...
has_many :users, though: :books
end
category = Category.includes(:users)
.find(params[:id])
users = category.users
参见:
[通过查看代码,我假设Book
模型也具有fiction_id
,因为此行has_many
中显示了Fiction.find(params[:ID]).books
关联。可能有两种方法可以实现此目的。第一个可能是您使用@filtered_books
变量并像@filtered_books.collect {|b| b.users}.flatten
一样从中提取用户以提取所有用户。第二种方法可能是通过使用fiction_id
的关联,可能类似于User.joins(:books).where(books: {id: @filtererd_books.pluck(:id)})