简体   繁体   English

在rails中显示相关记录

[英]Displaying associated records in rails

I have a User , List , and Task models. 我有一个UserListTask模型。

A task belongs_to user and list , a list has_many tasks and belongs_to user , and a user has_many list and has_many tasks . 任务 belongs_to 用户列表列表 has_many 任务belongs_to 用户 ,以及用户 has_many listhas_many 任务

I have part of what I want to display working in my index view, with just one snafu that I am getting hung up on. 我有一部分想要在我的索引视图中显示的内容,只有一个我想要挂起的snafu。

I'm able to display the first created task in the index view of all the lists. 我能够在所有列表的索引视图中显示第一个创建的任务。 The problem is, the first task created is displayed for all of the lists, even if the list is NOT associated with the task. 问题是,即使列表未与任务相关联,也会为所有列表显示创建的第一个任务。

In the list index view I want the first task created to display only if it is associated with the list. 在列表索引视图中,我希望创建的第一个任务仅在与列表关联时才显示。

Task model: 任务模型:

class Task < ActiveRecord::Base
  attr_accessible :completed, :description, :list_id, :user_id

  belongs_to :list
  belongs_to :user

  scope :completed, where(:completed => true)
  scope :incomplete, where(:completed => false)

  def self.most_recent
    first(:order => 'id ASC' ) # or whatever query you need to get the most recent
  end

end

List Index View- 列表索引视图 -

<div class="span12 offset2"> 
 <% @lists.each do |list| %> 
  <div class="well row span4">
    <div class="span3">
    </div>  
    <div class="span4">   
      <span class="lead">
        <%= link_to "#{list.name}", list_url(list) %>
      </span>
      <p>
        <%= list.description %>
      </p><hr>
      <div class="pull-right" id="gage-<%= list.id %>" style="width:170px; height:100px;"></div>
      <br>  
      <span class="offset1">
        <% if Task.most_recent %>
          <span class="pull-left"> <%= image_tag Task.most_recent.user.gravatar_url, :class => "gravatar_index" %></span>
        <% end %>  
      </span>
    </div>
  <% end %>
</div>

I'm still new to rails but I know I'm very close. 我还是铁杆新手,但我知道我非常接近。 What am I overlooking here? 我在这里俯瞰什么? emphasized text 强调文字

=========== ===========

EDIT 编辑

I've tested @Baldrick's solution and now seem to be getting another error 我已经测试了@Baldrick的解决方案,现在似乎又出现了另一个错误

My view with described solution- 我对所述解决方案的看法 -

<% if Task.most_recent(list) %>
      <span class="pull-left"> <%= image_tag Task.most_recent.user.gravatar_url, :class => "gravatar_index" %></span>
<% end %>

I am now getting the error- 我现在得到的错误 -

SQLite3::SQLException: no such column: tasks.list: SELECT  "tasks".* FROM "tasks"  WHERE "tasks"."list" = 4 ORDER BY id ASC LIMIT 1

I must not be understanding correctly because I have such a created column when I created the Task model 我不能正确理解,因为我在创建Task模型时有这样一个创建的列

class CreateTasks < ActiveRecord::Migration
  def change
    create_table :tasks do |t|
      t.string :description
      t.boolean :completed, :default => false
      t.integer :list_id

      t.timestamps
    end
  end
end

Is this a case where I need to add an index to be able to make my query? 这是一个我需要添加索引才能进行查询的情况吗?

The method most_recent gives you the last create task of all tasks. most_recent方法为您提供了所有任务的最后一个创建任务。 What you wnat is the most recent task of a given list. 你知道什么是给定列表的最新任务。

You should give a parameter to the list 您应该为列表指定一个参数

def self.most_recent(list)
  where(list_id: list.id).order('id ASC').first # or whatever query you need to get the most recent
end

Your most_recent method returns the first task of Task. 您的most_recent方法返回Task的第一个任务。 There is nothing in this method tying the task to any list. 此方法中没有任何内容将任务绑定到任何列表。 You'd need to pass the list_id to this method to get the first task for this list, eg 您需要将list_id传递给此方法以获取此列表的第一个任务,例如

def self.most_recent(list_id)
    first(:order => 'id ASC', :list_id => list_id) 
end

Edit: other solution didn't work. 编辑:其他解决方案无效。

Based on your description, it does not sound like you want, for each list, to show the most recent task for that list. 根据您的描述,它听起来并不像你想,每个列表,以显示该列表中的最近的任务。 Rather, it seems you want to have the overall most recent task to appear multiple times, once for each list that happens to contain it. 相反,似乎您希望将最近的总体任务多次出现,一次针对恰好包含它的每个列表。 To achieve this you want to replace if Task.most_recent with if list.tasks.include? Task.most_recent 为了达到这个目的,你想要将if Task.most_recent替换为if list.tasks.include? Task.most_recent if list.tasks.include? Task.most_recent . if list.tasks.include? Task.most_recent

---EDIT--- - -编辑 - -

Okay, if you actually want to show, for each list, that list's most recent task, then you should be going about this fairly differently. 好的,如果你真的想为每个列表显示该列表的最新任务,那么你应该以相同的方式进行此操作。 In your List class you should have the following method: List类中,您应该具有以下方法:

def most_recent_task
    tasks.first(:order => 'id ASC') # or whatever
end

Then in your view you'll replace both occurrences of Task.most_recent with list.most_recent_task . 然后,在你看来,你要换两次出现的Task.most_recentlist.most_recent_task And if your lists will always have at least one task, then you can get rid of the guard clause (ie the if ) altogether. 如果你的列表总是至少有一个任务,那么你可以完全摆脱保护条款(即if )。

As a further refactor you may want to take some computation out of the view, and create "presenters" for your lists index, which would just be an array of presenters for each individual list. 作为进一步的重构,您可能希望从视图中进行一些计算,并为列表索引创建“演示者”,这只是每个列表的演示者数组。 An individual presenter should be a plain object with the information you need about the list, precomputed: 单个演示者应该是一个普通对象,其中包含有关列表的所需信息,预先计算:

  • name 名称
  • url 网址
  • description 描述
  • most recent task's user's gravatar url 最近任务的用户的gravatar url

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

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