Rails - 查询连接表条件的更好方法

时间:2017-09-19 16:05:37

标签: ruby-on-rails activerecord

我正在玩一个桶清单,我有以下型号:

BucketList > BucketListItem < Item

BucketListItem是两者之间的连接表。

当我显示所有项目并允许用户将它们添加到自己的存储桶列表中或将其标记为完成时,我需要知道该用户是否在其存储桶列表中包含该项目,以及是否他们已将其标记为已完成或未完成。我想出了一个有效的解决方案,但感觉应该有更好的方法。

在控制器中:

@user_items = current_user.bucket_list.items
@user_bucket_list_items = current_user.bucket_list.bucket_list_items

@completed_user_items = []
current_user.bucket_list.bucket_list_items.where(status: 1).each do |bucket_list_item| 
  @completed_user_items << bucket_list_item.item
end

在呈现每个项目的部分中:

<% if @user_items.include?(item) %>
  <p>Added</p>
<% else %>
  <%= form_for(BucketListItem.new, remote: true) do |f| %>
    <%= f.hidden_field :item_id, value: item.id %>
    <%= f.submit "+ Add" %>
  <% end %>
<% end %>

<% if @completed_user_items.include?(item) %>
  <p>Done</p>
<% elsif @user_items.include?(item) %>
    <%= form_for(@user_bucket_list_items.where(item_id: item.id).first, remote: true) do |f| %>
      <%= f.hidden_field :status, value: "done" %>
      <%= f.submit "Mark as Done" %>
    <% end %>
<% else %>
    <%= form_for(BucketListItem.new, remote: true) do |f| %>
      <%= f.hidden_field :item_id, value: item.id %>
      <%= f.hidden_field :status, value: "done" %>
      <%= f.submit "Mark as Done" %>
    <% end %>
<% end %>

特别是第二个if声明对我来说有点令人费解。我错过了一种明显更简单的方法吗?

由于

1 个答案:

答案 0 :(得分:0)

明智的是,优化范围不大,但您可以在控制器中优化查询

#In Controller
@bucket_list = current_user.bucket_list
@user_items = @bucket_list.items
# More efficient way of getting item which are not yet completed
@completed_user_items = current_user.items.where(bucket_list_items: { status: 1 })


#In view
<% if @user_items.include?(item) %>
  <p>Added</p>
<% else %>
  <%= form_for(BucketListItem.new, remote: true) do |f| %>
    <%= f.hidden_field :item_id, value: item.id %>
    <%= f.submit "+ Add" %>
  <% end %>
<% end %>

<% if @completed_user_items.include?(item) %>
  <p>Done</p>

#Here I have used @bucket_list
<% elsif @user_items.include?(item) %>
    <%= form_for(item.bucket_list_items.where(bucket_list: @bucket_list).first, remote: true) do |f| %>
      <%= f.hidden_field :status, value: "done" %>
      <%= f.submit "Mark as Done" %>
    <% end %>
<% else %>
    <%= form_for(BucketListItem.new, remote: true) do |f| %>
      <%= f.hidden_field :item_id, value: item.id %>
      <%= f.hidden_field :status, value: "done" %>
      <%= f.submit "Mark as Done" %>
    <% end %>
<% end %>