繁体   English   中英

如何连接表并为活动记录 RAILS 应用 where 子句

[英]How to join tables and apply where clause for active record RAILS

这似乎是一件非常简单的事情,但是尽管查看了 rails 文档,但它并没有像我预期的那样工作。 我可能在某处做出了不正确的假设。 也许我正试图让 activerecord 用于它不打算用于的东西?

我正在尝试加入我的 Books 表和 Checkout_logs 表,并且只返回与 user_id 匹配且返回日期为 null 的记录(无)

我正在尝试在 sql 中执行类似此示例的操作(除了列出所有书籍信息,而不仅仅是标题并从参数中获取 user_id)

select b.title,c.due_date from 
(select * from books) b
JOIN
(select * from checkout_logs) c
ON b.id = c.book_id
where c.user_id = 1 and returned_date is null

这是我的尝试

book_controller.rb

def my_books    
    @books = Book.joins(:checkout_logs).where(user_id: params[:user_id], returned_date: nil)
  end

并查看

my_books.html.erb

<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Author</th>
      <th>Genre</th>
      <th>Subgenre</th>
      <th>Pages</th>
      <th>Publisher</th>      
      <th>due_date</th>
      <th colspan="1"></th>
    </tr>
  </thead>

  <tbody>
    <% @books.each do |book| %>
      <tr>
        <td><%= link_to book.title, book %></td>
        <td><%= book.author %></td>
        <td><%= book.genre %></td>
        <td><%= book.subgenre %></td>
        <td><%= book.pages %></td>
        <td><%= book.publisher %></td>
        <td><%= book.due_date %></td>
        <td><%= link_to 'Return', books_return_path %></td>        
      </tr>
    <% end %>
  </tbody>
</table>

书本.rb

class Book < ApplicationRecord
    has_many :checkout_logs, dependent: :destroy
end

checkout_log.rb

class CheckoutLog < ApplicationRecord
  belongs_to :user
  belongs_to :book
end

在加载 book.user_id 不存在或 books.due_date 不存在的视图时会出错。 我知道书籍没有这些东西,但我认为通过将其与 checkout_log 加入我就可以通过这种方式访问它们?

我更愿意在 activerecord 中学习如何执行此操作,因为我认为这是最佳实践。 我愿意使用另一种方法。 我有另一个使用 AREL 执行类似操作的页面,但如果我可以学习如何更好地使用 activerecord,我更愿意清理它。

您可以通过将.to_sql传递给查询来调试查询

 @books = 
   Book
   .joins(:checkout_logs)
   .where(user_id: params[:user_id], returned_date: nil)

在这种情况下,我认为问题在于where条件是针对books表而不是checkout_logs表。 你可以通过这样做来解决这个问题

.where(checkout_logs: { user_id: params[:user_id], returned_date: nil })

问题是 where 子句。 在 where 子句中,需要遍历关系才能访问正确表上的属性。 book 表上没有 user_id。 我假设返回的日期也在 CheckoutLog 表上。 如果您对此进行查询,则应该没问题。

Book.joins(:checkout_logs).where(checkout_logs: {user_id: params[:user_id], returned_date: nil})

要在此处获取结帐日志信息,您需要遍历关系。

@book.checkout_logs.each do |log|
  puts log.due_date
  ...
end

执行上述操作的更好方法是使用包含和/或引用来急切加载相关的结帐日志以减少 n+1 问题

如果您只想要 CheckoutLog 记录,那么您需要从 model 开始。

CheckoutLog.where(book_id: <BOOK ID>, user_id: params[:user_id], returned_date: nil)

然后,您可以遍历视图中的那些,以获取您需要的任何结帐日志信息。

所以我需要在

book_controllers.rb

@checkout_logs = CheckoutLog.joins(:book).where(checkout_logs: {user_id: current_user.id, returned_date: nil})

然后视图可以通过执行以下操作访问这本书:

my_books.html.erb

<% @checkout_logs.each do |checkout_log| %>
      <tr>
        <td><%= checkout_log.book.title %></td>
        <td><%= checkout_log.book.author %></td>
        <td><%= checkout_log.book.genre %></td>
        <td><%= checkout_log.book.subgenre %></td>
        <td><%= checkout_log.book.pages %></td>
        <td><%= checkout_log.book.publisher %></td>
        <td><%= checkout_log.due_date %></td>
        <td><%= link_to 'Return', books_return_path(:checkout_log_id => checkout_log.id) %></td>        
      </tr>
    <% end %>

因为 checkout_log 有 1 本书,所以我可以通过这种方式访问这本书。 我无法以其他方式访问信息,也无法创建一些将所有信息都放在同一级别上的混合体。 (至少我做不到)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM