我正在学习RoR,但我无法从相关的表中获取值来显示。我已经尝试了here和here提到的建议,但我仍然没有让它发挥作用。
我的客户记录与联系人有一对多的关系。
以下是我模特的剪辑:
class Contact < ActiveRecord::Base
belongs_to :customer
class Customer < ActiveRecord::Base
has_many :contacts, dependent: :destroy
这是我的联系人index.html.erb产生错误
<% @contacts.each do |contact| %>
<tr class="<%= cycle("even pointer", "odd pointer") %>">
<td><%= contact.first_name %> <%= contact.last_name %></td>
<td><%= contact.customer.name %></td> <!-- this is the error line -->
<td><%= contact.office_phone %></td>
<td><%= contact.cell_phone %></td>
<td><a href="<%= contact.email %>"><%= contact.email %></a></td>
<td>
<% if current_user.admin? %>
<%= link_to "edit", contact, method: :edit %>
<% end %>
</td>
</tr>
<% end %>
我得到的错误是:nil的未定义方法`name':NilClass
我做错了什么?在我看来,就像我引用该字段的方式,我实际上并没有得到Customers表中的数据,但我不太确定。我是否在模型中正确建立了关系?
更新以添加控制器代码
class ContactsController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :new, :create]
def index
@contacts = Contact.paginate(page: params[:page])
end
def show
@contact = Contact.find(params[:id])
end
def new
@contact = Contact.new
end
def create
@contact = Contact.new(contact_params)
if @contact.save
flash[:success] = "Contact created!"
redirect_to @contact
else
render 'new'
end
end
def edit
@contact = Contact.find(params[:id])
end
def update
@contact = Contact.find(params[:id])
if @contact.update_attributes(contact_params)
flash[:success] = "Contact updated"
redirect_to @contact
else
render 'edit'
end
end
private
def contact_params
params.require(:contact).permit(:first_name, :last_name, :email, :address1,
:address2, :office_phone, :cell_phone, :website, :city, :zip, :facebook, :twitter)
end
end
class CustomersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :new, :create]
def index
@customers = Customer.paginate(page: params[:page])
end
def show
@customer = Customer.find(params[:id])
end
def new
@customer = Customer.new
end
def create
end
def edit
@customer = Customer.find(params[:id])
end
def update
@customer = Customer.find(params[:id])
if @customer.update_attributes(customer_params)
flash[:success] = "Customer updated"
redirect_to @customer
else
render 'edit'
end
end
private
def customer_params
params.require(:customer).permit(:name, :email, :address1,
:address2, :phone, :fax, :website, :city, :zip, :facebook, :duns_number)
end
end
修改 这是我的contact.html.erb表单。
<%= form_for @contact, html: { class: "form-horizontal form-label-left" } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :first_name, nil, class: 'control-label col-md-3 col-sm-3 col-xs-12' %>
<div class="col-md-6 col-sm-6 col-xs-12">
<%= f.text_field :first_name, class: 'form-control col-md-7 col-xs-12' %>
</div>
</div>
<div class="form-group">
<%= f.label :last_name, nil, class: 'control-label col-md-3 col-sm-3 col-xs-12' %>
<div class="col-md-6 col-sm-6 col-xs-12">
<%= f.text_field :last_name, class: 'form-control col-md-7 col-xs-12' %>
</div>
</div>
<div class="form-group">
<%= f.label :customer_id, nil, class: 'control-label col-md-3 col-sm-3 col-xs-12' %>
<div class="col-md-6 col-sm-6 col-xs-12">
<%= select_tag :customer_id, options_for_select(Customer.all.collect {|c| [ c.name, c.id ] }), class: 'form-control' %>
</div>
</div>
<div class="form-group">
<%= f.label :office_phone, nil, class: 'control-label col-md-3 col-sm-3 col-xs-12' %>
<div class="col-md-6 col-sm-6 col-xs-12">
<%= f.text_field :office_phone, class: 'form-control col-md-7 col-xs-12' %>
</div>
</div>
<div class="ln_solid"></div>
<div class="form-group">
<div class="col-md-6 col-sm-6 col-xs-12 col-md-offset-3">
<%= f.submit "Save changes", class: "btn btn-primary" %>
</div>
</div>
<% end %>
答案 0 :(得分:2)
您正确引用它。
您的contact
似乎尚未保存到数据库中。这将导致关系尚不存在。
您可能需要以不同方式创建关系。
我通常会这样做:
customer = Customer.create
customer.contacts << Contact.create({first_name: 'John', last_name: 'Smith'})
立即创建与DB的关联和提交。然后,在同一请求中,您的contact
customer
将被设置并可访问。
你也可以这样做,但这有点多余:
customer = Customer.create
customer.contacts << Contact.create({first_name: 'John', last_name: 'Smith', customer: customer})
修改强>
似乎您可能需要在创建/更新联系人时为其分配客户。在您的联系表单中,您可能需要这样的内容(在此处查看您现有的表单会有所帮助):
<%= select_tag :customer_id, options_for_select(Customer.all.collect {|c| [ c.name, c.id ] }) %>
或(使用simple_form):
f.input :customer_id, collection: Customer.all, selected: @contact.customer_id
# or more simply
f.association :customer
如果您在构建表单时了解客户,则可能是隐藏的表单字段:
f.input :customer_id, as: :hidden, value: @customer.id
然后在您的控制器中,将customer_id
添加到contact_params
,如下所示:
def contact_params
params.require(:contact).permit(
:first_name, :last_name, :email, :address1,
:address2, :office_phone, :cell_phone,
:website, :city, :zip, :facebook, :twitter,
:customer_id
)
end
答案 1 :(得分:1)
尝试.try() activesupport方法:
<td><%= contact.customer.try(:name) %></td>
如果contact.customer
为零(联系人不是belongs_to
客户),则不会调用:name
方法。
更新另一个提示:
一个。没有客户,你有联系是件坏事。考虑将此添加到您的模型中:
class Contact < ActiveRecord::Base
...
validates :customer, presence: true
湾您可以替换代码:
<tr class="<%= cycle("even pointer", "odd pointer") %>">
与
<%= content_tag :tr, class: cycle('event pointer', 'odd pointer') %>
℃。替换这个:
<a href="<%= contact.email %>"><%= contact.email %></a>
用这个:
<%= mail_to contact.email, contact.customer.try(:name) %>
答案 2 :(得分:1)
通常这可以帮助
例如,您有2个表City和Post,每个帖子都有city_id,并且您想在视图中显示与该帖子关联的城市的名称,您应该在视图中调用bloc,然后调用表的名称然后是这样的列名称:
<% @post.each do |post| %>
<%= post.city.name %
<% end %>