0

当谈到 RoR 时,我非常乐观,并且无法确定我的问题是由我的模型关联中的问题引起的,还是我只是没有使用正确的语法来访问数据。

一个用户可以有很多预算。每个预算都由多个明细行组成。我认为budget_details 中不需要用户ID,因为它已在预算中捕获,因此可以通过三者之间的关系来推断(也许?!)

在budget_details 索引中,我希望能够包含用户名;我让它在“显示”视图中工作,但不是索引。

我确实使用了脚手架来设置这些,所以我知道那里有很多杂物,我只是想做一个例子,然后再转移到一个新项目来真正做到这一点。

实际错误是;

NoMethodError in Budget_details#index

Showing C:/Sites/example1/app/views/budget_details/index.html.erb where line #17 raised:

undefined method `name' for nil:NilClass

我不明白为什么这会失败,但 show 方法有效?是和范围有关吗?即显示是在单实例级别,而索引是在“全部”级别,所以它无法在用户中找到数据?

非常感谢任何帮助

楷模:

用户.rb

class User < ActiveRecord::Base
attr_accessible :email, :name

has_many :budgets
has_many :budget_details, :through => :budgets

预算.rb

class Budget < ActiveRecord::Base
attr_accessible :budget_name, :user_id

belongs_to :user
has_many :budget_details

Budget_details.rb

class BudgetDetail < ActiveRecord::Base
attr_accessible :amount, :amount_type, :budget_id, :itemname

belongs_to :budget

控制器 - budget_details_controller.rb

class BudgetDetailsController < ApplicationController
# GET /budget_details
# GET /budget_details.json
def index
  @budget_details = BudgetDetail.all
  @users = User.all

    respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @budget_details }
  end
end

# GET /budget_details/1
# GET /budget_details/1.json
def show
  @budget_detail = BudgetDetail.find(params[:id])
  @user = User.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
    format.json { render json: @budget_detail }
  end
end
.....

show.html.erb <%= 通知 %>

<p>
  <b>Username:</b>
  <%= @user.name %>
</p>

<p>
  <b>Budget:</b>
  <%= @budget_detail.budget_id %>
</p>

<p>
  <b>Itemname:</b>
  <%= @budget_detail.itemname %>
</p>

<p>
  <b>Amount:</b>
  <%= @budget_detail.amount %>
</p>

<p>
  <b>Amount type:</b>
  <%= @budget_detail.amount_type %>
</p>
<%= link_to 'Edit', edit_budget_detail_path(@budget_detail) %> |
<%= link_to 'Back', budget_details_path %>

index.html.erb

<h1>Listing budget_details</h1>

<table>
  <tr>
    <th>Username</th>
    <th>Itemname</th>
    <th>Budget</th>
    <th>Amount</th>
    <th>Amount type</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @budget_details.each do |budget_detail| %>
  <tr>
    <td><%= @user.name %></td>
    <td><%= budget_detail.itemname %></td>
    <td><%= budget_detail.budget_id %></td>
    <td><%= budget_detail.amount %></td>
    <td><%= budget_detail.amount_type %></td>
    <td><%= link_to 'Show', budget_detail %></td>
    <td><%= link_to 'Edit', edit_budget_detail_path(budget_detail) %></td>
    <td><%= link_to 'Destroy', budget_detail, method: :delete, data: { confirm: 'Are    you sure?' } %></td>
  </tr>
<% end %>
</table>

<br />
4

2 回答 2

1

在您的index.html.erb文件中:

<td><%= @user.name %></td>

你没有@user在你的index行动中定义 - 因此错误。

如果仅使用关联,您可以避免此问题并完全直接拉@user入控制器以执行任一操作:

<td><%= budget_detail.user.name %></td>

并且为了避免这样做(N + 1)的性能损失,您可以使用以下命令将它们预先加载到您的控制器中includes

@budget_details = BudgetDetail.includes(:user).all

然而,这个关联还不存在——你需要在你的班级中添加一个“has-one-through”关系BudgetDetail——这与你为班级所做的相反User

has_one :user, :through => :budget

总结一下

您应该将user关联添加BudgetDetail为“has-one-through”。

您的控制器操作应如下所示:

def index
  @budget_details = BudgetDetail.includes(:user).all

  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @budget_details }
  end
end

def show
  @budget_detail = BudgetDetail.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
    format.json { render json: @budget_detail }
  end
end

在您看来,不要使用@user.name

<%= budget_detail.user.name %>
于 2013-01-24T20:15:50.153 回答
1

错误表示@user.name错误,因为@user是零。

在您的控制器中,您目前似乎在获取:

def index
  @budget_details = BudgetDetail.all
  @users = User.all 
end    

def show
  @budget_detail = BudgetDetail.find(params[:id])
  @user = User.find(params[:id]) # THIS WOULD MEAN THAT A USER HAS THE SAME ID AS THE BUDGET_DETAIL
end

当索引操作获取索引模板的变量时,您会看到您没有在此处获取任何变量@user,只是一个@users包含所有用户的变量。

相反,您应该删除两个操作中的用户获取,并通过budget_detail.user关联在视图中获取它们。

def index
  @budget_details = BudgetDetail.all
end    

def show
  @budget_detail = BudgetDetail.find(params[:id])
end

显示.html.erb

<p>
  <b>Username:</b>
  <%= @budget_detail.user.name %>
</p>

<% @budget_details.each do |budget_detail| %>
  <tr>
    <td><%= budget_detail.user.name %></td>
    ...
  </tr>
<% end %>
于 2013-01-24T20:18:58.470 回答