在 rails 中显示关联的记录

Posted

技术标签:

【中文标题】在 rails 中显示关联的记录【英文标题】:Displaying associated records in rails 【发布时间】:2012-10-28 08:43:50 【问题描述】:

我有 UserListTask 模型。

一个任务belongs_to用户列表,一个列表has_many任务 和 belongs_to user,以及 user has_many listhas_many tasks

我想要在我的索引视图中显示的部分内容正在工作,只有一个让我挂断的问题。

我能够在所有列表的索引视图中显示第一个创建的任务。问题是,为所有列表显示创建的第一个任务,即使列表与任务无关。

在列表索引视图中,我希望创建的第一个任务仅在与列表关联时才显示。

任务模型:

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

列表索引视图-

<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>

我对 Rails 还是很陌生,但我知道我已经很接近了。我在这里俯瞰什么? 强调文字

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

编辑

我已经测试了@Baldrick 的解决方案,现在似乎又遇到了另一个错误

我对所描述解决方案的看法-

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

我现在收到错误-

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

我一定没有正确理解,因为我在创建任务模型时创建了这样一个列

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

这是我需要添加索引才能进行查询的情况吗?

【问题讨论】:

每个块缺少的&lt;% end %&gt; 只是一个错字吗? 没错,它在 c 和 p 上被忽略了。 抱怨是因为使用了列表而不是 list_id。这是因为@Baldrick 的代码中有错误。在 most_recent 方法中,该方法应该与我在答案中作为第一选择的方法一样。使用 Baldrick 的代码,应该是where(list_id: list).order('id ASC').first 【参考方案1】:

most_recent 方法为您提供所有 个任务的最后一个创建任务。您需要的是给定列表的最新任务。

你应该给列表一个参数

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

【讨论】:

我的观点是一样的,除了传递列表作为参数Task.most_recent(list)? 这是我最终采用的解决方案。请参阅@jtblin 对此解决方案的评论,因为这是我使此解决方案起作用的唯一方法。 应该是where(list_id: list.id) 还是你真的可以只做where(list_id: list) 我不确定,所以我用list_id: list.id编辑了答案。【参考方案2】:

您的most_recent 方法返回Task 的第一个任务。此方法中没有任何内容将任务绑定到任何列表。您需要将 list_id 传递给此方法以获取此列表的第一个任务,例如

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

编辑:其他解决方案无效。

【讨论】:

得到一个undefined method most_recent' 的#<:relation:0x007f8cb9bcc030>` 错误。在我看来,我现在会有&lt;%= image_tag list.tasks.most_recent.user.gravatar_url, :class =&gt; "gravatar_index" %&gt; 好的,我只保留第一个选项,请按原样尝试,它应该可以正常工作。【参考方案3】:

根据您的描述,听起来确实像您想要的那样,对于每个列表,显示该列表的最新任务。相反,您似乎希望 overall 最近的任务多次出现,每个列表恰好包含它一次。为此,您需要将if Task.most_recent 替换为if list.tasks.include? Task.most_recent

---编辑---

好的,如果您真的想为每个列表显示该列表的最近的任务,那么您应该以完全不同的方式进行处理。在您的 List 类中,您应该有以下方法:

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

然后在您看来,您将用list.most_recent_task 替换两个出现的Task.most_recent。如果您的列表总是至少有一项任务,那么您可以完全摆脱保护子句(即if)。

作为进一步的重构,您可能希望从视图中进行一些计算,并为您的列表索引创建“演示者”,这将只是每个单独列表的演示者数组。单个演示者应该是一个普通对象,其中包含您需要的关于列表的信息,预先计算:

姓名 网址 说明 最近任务用户的头像url

【讨论】:

这不是我想要的。我希望它就像您有彼此不相关的单独列表,因此任务将是不相关的。我确实想显示该列表的最新任务:) 是的,这很可能是我在重构后将采用的方法,据我所知,从惯例和工作流程的角度来看,应该尽早完成。也就是说,感谢您添加到您的答案。

以上是关于在 rails 中显示关联的记录的主要内容,如果未能解决你的问题,请参考以下文章

在 Rails 中审计记录

想在 Rails 中查找没有关联记录的记录

如何正确销毁 ruby​​ on rails 中的关联记录?

硬删除在rails中启用软删除的关联记录

如何在 Rails 2.3.8 中使用带有关联的 Active 脚手架列出活动记录?

如何在整个 Rails 活动记录关联链中取消特定模型的默认范围?