返回类实例的返回属性

时间:2015-04-30 16:46:17

标签: ruby-on-rails ruby ruby-on-rails-4

基本上我在页面base视图上有一个表格输出。标头(milestones)通过传递Milestones类并使用.each do进行迭代来动态集成。然后,最初通过执行相同操作生成表行,将clienttradeunits拉入前三列。其余列应为日期(类entry属性due),这些日期是使用循环可访问的clienttrade属性查找排序计算的,并且在为标题动态生成数组时创建的数组可访问的milestone ID。这一切都正常工作,表生成正常..但日期输出为#<Entry:0x000000056faa90>,依此类推。

现在我遇到过这个问题,基本上修复是添加一个类定义并告诉它返回我认为是该实例的属性。例如:

class Client < ActiveRecord::Base
    validates :id,      presence:true
    validates :client,  presence:true

    def name
        return self.client
    end
end

这很有效,但仅限于我如何访问客户端。不幸的是,我以不同方式访问entry.due。这是我的相关代码。

base_controller.rb

class BaseController < ApplicationController

  def index
    @trades = Trade.all
    @milestones = Milestone.all
    #@entries = Entry.all  #Didn't seem relevant to how I am trying to access the information.
  end
end

entry.rb

class Entry < ActiveRecord::Base
  belongs_to :client
  belongs_to :trade
  belongs_to :milestone

  validates :client,    presence:true
  validates :trade,     presence:true
  validates :milestone, presence:true
  validates :due,       presence:true

  # Some of my trial and error; all to no avail.
  def due
    return self.due
  end

  def self.due
    return self.due
  end

  def pickDue(c,t,m)
    ret = self.select("date_format(due, '%m/%d/%Y')").where("client_id=? AND trade_id=? AND milestone_id=?", c, t, m).first
    return ret
  end
end

base&gt; index.html.erb

<table>
  <thead>
    <tr class="sort">
      <th>Client</th>
      <th>Trade</th>
      <th>Units</th>

      <% 
          ms = []
          @milestones.each do |milestone|
          ms.push(milestone)
      %>
        <th><%= milestone.name %></th>
      <% end %>

    </tr>
  </thead>

  <tbody>
    <% @trades.order("entered").last(10).each do |trade| %>
      <tr>
        <td><%= trade.client.name %></td>
        <td><%= trade.name %></td>
        <td><%= trade.units %></td>

        <% ms.each do |msr| %>
            <td>
              <%= Entry.select("date_format(due, '%m/%d/%Y')").where("client_id=? AND trade_id=? AND milestone_id=?", trade.client, trade, msr).first %>
              <%#= Entry.pickDue(trade.client, trade, msr) %>
            </td>
        <% end %>
      </tr>
    <% end %>
  </tbody>
</table>

通过这种方法,我可以无错误地加载页面,但我没有显示日期,而是显示#<Entry:0x000000056faa90>之类的对象。

如果我将.due添加到选择器的末尾:

<%= Entry.select("date_format(due, '%m/%d/%Y')").where("client_id=? AND trade_id=? AND milestone_id=?", trade.client, trade, msr).first.due %>
# undefined method `due' for nil:NilClass

如果我在其他任何地方添加.due

<%= Entry.due.select("date_format(due, '%m/%d/%Y')").where("client_id=? AND trade_id=? AND milestone_id=?", trade.client, trade, msr).first %>
<%= Entry.select("date_format(due, '%m/%d/%Y')").due.where("client_id=? AND trade_id=? AND milestone_id=?", trade.client, trade, msr).first %>
<%= Entry.select("date_format(due, '%m/%d/%Y')").where("client_id=? AND trade_id=? AND milestone_id=?", trade.client, trade, msr).due.first %>
# stack level too deep

我已经尝试了几十种不同的方法,这些方法通过几天的搜索而没有运气。除了输出对象而不是对象属性的当前情况之外,我认为下一个最接近的是当我收到错误时说它无法找到due对象的ActiveRecord方法,但我不记得怎么得到这个错误。

我真的很感激任何意见。

1 个答案:

答案 0 :(得分:1)

如果我理解正确,我会在你的模型中删除试用和错误代码,然后在你看来你可以这样称呼:

Entry.where(client: trade.client, milestone: msr, trade: trade).pluck(:due)

这会在您的视图中进入里程碑循环,如下所示:

    <% ms.each do |msr| %>
        <td>
          <%= Entry.where(client: trade.client, milestone: msr, trade: trade).pluck(:due).first %>
        </td>
    <% end %>

Pluck从您指定的列返回一组值(请参阅iTunes Link Maker,因此请注意.first方法是Array#first方法,而不是ActiveQuery#first方法。您甚至可以创建一个同时传递所有里程碑的查询,而不是为每个里程碑运行查询,从而防止出现N + 1查询情况。

那将是:

<% Entry.where(client: trade.client, trade: trade, milestone: ms).pluck(:due).each do |entry_due_date| %>
  <td>
    <%= entry_due_date %>
  </td>
<% end %>

最后,虽然我在视图中为您提供了SQL查询的代码,但在Rails中通常认为在您的视图中编写SQL查询是不好的做法,您应该将其作为Entry模型中的方法。