【问题标题】:Ruby on Rails - Display field from related tableRuby on Rails - 显示相关表中的字段
【发布时间】:2015-09-11 19:58:06
【问题描述】:

我正在学习 RoR,但无法从相关表中获取要显示的值。我已经尝试了herehere 提到的建议,但我仍然没有得到它的工作。

我有一个与联系人具有一对多关系的客户记录。

以下是我的模型截图:

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:NilClass 的未定义方法“名称”

我做错了什么?在我看来,我引用字段的方式似乎并没有真正获取客户表中的数据,但我不太确定。我是否在模型中正确建立了关系?

更新以添加控制器代码

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

【问题讨论】:

  • 我们也来看看控制器代码。你要采取什么行动?
  • 我为我的控制器添加了代码。
  • 谢谢。我假设您正在为客户建立联系。您可以发布您的联系表格吗?我认为我们需要在某处获得一个客户字段。联系人是否以嵌套形式创建?你在使用嵌套路由吗?

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


【解决方案1】:

您正确地引用了它。

您的contact 似乎尚未保存到数据库中。这将导致关系不存在。

您可能需要以不同的方式创建关系。

我通常会这样做:

 customer = Customer.create
 customer.contacts << Contact.create({first_name: 'John', last_name: 'Smith'})

它会立即创建关联并提交给数据库。然后,在同一个请求中,您的contactcustomer 将被设置和访问。

你也可以这样做,但是有点多余:

 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

【讨论】:

  • 谢谢卡尔。我通过尝试在我的种子文件中创建关系来测试这个,所以也许我需要看看那里。使用 asiniy 推荐的 try() 方法会显示名称的所有空白,所以也许我确实对记录有问题。
  • 我现在看到你的控制器了,谢谢。在您的控制器中,您没有在任何地方创建关系。当您创建或更新时,您需要传入相关对象,至少是对象 ID。
  • 感谢您的帮助。我现在正朝着正确的方向前进,但我仍然无法添加新联系人。我得到的错误是公司不能为空....但是我选择了一家公司。关于为什么的任何猜测?我也更新了我的联系人控制器代码。
  • 您的contact_params 需要允许:customer_id
  • 再次感谢@Karl Wilbur,我将其添加到联系人中,但我得到了同样的错误。我掉到 Rails 控制台并尝试验证 ActiveRecord::RecordInvalid: Validation failed: Customer can't be blank
【解决方案2】:

试试.try()activesupport方法:

<td><%= contact.customer.try(:name) %></td>

如果contact.customer 为零(联系人不是belongs_to 客户),则不会调用:name 方法。

已更新其他提示:

一个。这是一件坏事,你有一个没有客户的联系。考虑将此添加到您的模型中:

class Contact < ActiveRecord::Base
  ...

  validates :customer, presence: true

b.你可以这样替换代码:

<tr class="<%= cycle("even pointer", "odd pointer") %>">

<%= content_tag :tr, class: cycle('event pointer', 'odd pointer') %>

c。替换这个:

<a href="<%= contact.email %>"><%= contact.email %></a>

用这个:

<%= mail_to contact.email, contact.customer.try(:name) %>

【讨论】:

  • 感谢@asiniy,当我使用 try() 方法时,页面会加载,但整个表格中的字段都是空白的。当我对电子邮件地址使用建议的更改时,它可以完美运行。知道为什么一个可以工作而另一个不行吗?
【解决方案3】:

通常这会有所帮助

例如,您有 2 个表 City 和 Post,每个帖子都有 city_id 并且您想在视图中显示与帖子关联的城市名称,您应该在视图中调用 bloc 然后是表的名称然后是这样的列名称:

<% @post.each do |post| %>   
   <%= post.city.name %
<% end %>

【讨论】:

    猜你喜欢
    • 2015-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多