【问题标题】:Extracting data using rails query from a join table使用 rails 查询从连接表中提取数据
【发布时间】:2020-04-07 02:34:31
【问题描述】:

我有 users 表、 books 表和 books_users 加入表。在 users_controller.rb 中,我正在尝试提取已过滤的用户。请帮我解决这个问题。

用户.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 不使用连接模型,所以如果您使用 HABTM,BooksUser 完全是多余的。然后,您只需向我们发送Fiction 即可,而无需告诉我们有关这种关系的任何信息,甚至您想用它来完成什么。如果它试图进行分类,你错过了标记。
  • 还有params[:ID] != params[:id]。大小写在 ruby​​ 中很重要。

标签: ruby-on-rails postgresql ruby-on-rails-5


【解决方案1】:

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

见:

【讨论】:

    【解决方案2】:

    通过查看代码,我假设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)})

    【讨论】:

    • 有很多方法可以做到这一点,而不是将所有内容从数据库中提取出来并将其转换为 id 数组。这不是一个好方法。
    • Pluck 在这里也不起作用,因为它是一种查询方法,您已经使用 collect 将其分解为一个数组。你必须这样做.map(&amp;:id)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 2017-07-07
    • 2023-03-07
    • 2014-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多