当涉及到RoR时,我非常环保,并且无法弄清楚我的问题是否是由我的模型关联中的问题引起的,或者我是否只是使用正确的语法来访问数据。 / p>
用户可以有很多预算。每个预算由多个细节线组成。我认为budget_details中不需要用户ID,因为它是在预算中捕获的,因此可以通过三者之间的关系推断出来(可能是?!)
在budget_details索引中,我希望能够包含用户名;我已经让它在'show'视图中工作,但不是索引。
我确实使用了一个脚手架来设置它们,所以我知道那里有很多不好的东西,我只是想在做一个新的项目之前做一个例子来实现它。
实际错误是;
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方法有效?是否与范围有关?即show是单实例级别而index是'all'级别,因此无法在Users中找到数据?
任何帮助非常感谢
型号:
User.rb
class User < ActiveRecord::Base
attr_accessible :email, :name
has_many :budgets
has_many :budget_details, :through => :budgets
Budget.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
Controller - 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 &lt;%= notice%&gt;
<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 />
答案 0 :(得分: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
但是,此关联尚不存在 - 您需要为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 %>
答案 1 :(得分: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
show.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 %>