未定义的方法`[]'为nil:创建表单时为NilClass

时间:2013-08-12 16:10:57

标签: ruby-on-rails ruby-on-rails-3

我是Rails的新手(以及一般的编码),我似乎无法弄清楚这种形式有什么问题。

用例: 我的网站有多家公司。每家公司都可以有多个地点。在公司展示页面上,我需要能够添加/删除位置。

Company Model:
class Company < ActiveRecord::Base
  attr_accessible :company_name, :company_website

  has_many :company_interests
  has_many :interests, through: :company_interests

  has_many :company_locations
  has_many :locations, through: :company_locations

    def add_location!(location)
        company_locations.create!(location_id: location.id)
    end

    def remove_location!(location)
        company_locations.find_by_location_id(location.id).destroy
    end

    def has_location?(location)
        company_locations.find_by_location_id(location.id)
    end
end

位置模型:

class Location < ActiveRecord::Base
  attr_accessible :city
  validates :city, presence: true, uniqueness: true

  has_many :company_locations
  has_many :companies, through: :company_locations 
end

和CompanyLocation模型:

class CompanyLocation < ActiveRecord::Base
  attr_accessible :company_id, :location_id

  belongs_to :company
  belongs_to :location
end

在我的公司控制器中,我在视图中提供了所有公司和位置:

def show
    @company = Company.find(params[:id])
    @locations = Location.all
end

在“显示”视图中,我列出了所有位置并显示了添加/删除位置的表单:

<% provide(:title, @company.company_name) %> 
<div class="row">
    <aside class="span4">
        <section>
            <h1>
                <%= @company.company_name %>
            </h1>
            <p>
                <%= @company.company_website %>
            </p>
            <p>
                <%= link_to "Edit Profile", edit_company_path(@company) %>
            </p>
        </section>
        <section>
            <div>
              <h1>Associations</h1>
              <p>Locations: <%= link_to @company.locations.count, "#" %>
              <p>Interests <a href="#">7</a></p>
            </div>
        </section>
    </aside>
    <div class="span8">
        <h3>Company Locations</h3>
        <ol class="locations">
            <% @locations.each do |location| %>
            <li>
                <span class="locations">
                    <%= location.city %>
                    <div>
                        <% if @company.has_location?(location) %>

                            <%= form_for(@company.company_locations.find_by_location_id(location.id),
                                            html: { method: :delete }) do |f| %>
                            <%= f.submit "Remove", class: "btn btn-large" %>
                            <% end %>
                        <% else %>
                            <%= form_for(@company.company_locations.build(location_id: location.id)) do |f| %>
                                <div><%= f.hidden_field :location_id %></div>
                                <div><%= f.hidden_field :company_id %></div>
                                <%= f.submit "Add", class: "btn btn-large btn-primary" %>
                            <% end %>
                        <% end %>
                    </div>
                </span>
            </li>
            <% end %>
        </ol>
    </div>
</div>

这是CompanyLocations控制器:

class CompanyLocationsController < ApplicationController
    def create
    @location = Location.find(params[:company_location][:location_id])
    @company = Company.find(params[:company_location][:company_id])
    @company.add_location!(@location)
    redirect_to @company
  end

  def destroy
        @location = Location.find_by_location_id(params[:company_location][:location_id])
        #@company = Company.find(params[:company_location][:company_id])
        #@company_location = @company.company_locations.find_by_location_id(params[:company_location][:location_id])
        #@company_location = Location.find(params[:company_location][:location_id])
    #@company = Company.find(params[:company_location][:company_id])
    @company.remove_location!(location)
    redirect_to @company
  end
end

添加位置工作正常,但是当我尝试删除一个时出现以下错误:

NoMethodError in CompanyLocationsController#destroy
undefined method `[]' for nil:NilClass
app/controllers/company_locations_controller.rb:10:in `destroy'
Parameters:

{"utf8"=>"✓",
 "_method"=>"delete",
 "authenticity_token"=>"CSeDt/aquzCyf55k4Y0Nz6O9/bwWO6gmLrd4dK/Tt08=",
 "commit"=>"Remove",
 "id"=>"1"}

我觉得有一些我不明白如何在表单中调用特定的companylocation对象,但我无法弄明白。请帮忙!

1 个答案:

答案 0 :(得分:0)

从您的错误日志中,您应该能够辨别出您从客户端收到的参数,没有像“company_location”=&gt; {'location_id'=&gt;这样的参数。 xxx}但只有id =&gt; 1。

这是您在form_for构建器中从@ company.company_locations.find_by_location_id(location.id)获得的ID。

 <%= form_for(@company.company_locations.find_by_location_id(location.id),
                                        html: { method: :delete }) do |f| %>

所以@meagar和@MrYoshiji说你需要的只是一个简单的@location = Location.find params[:id]

顺便说一句,你的模态中有很多冗余代码,你不需要像

这样的getter或setter函数
def add_location!(location)
    company_locations.create!(location_id: location.id)
end

def remove_location!(location)
    company_locations.find_by_location_id(location.id).destroy
end

def has_location?(location)
    company_locations.find_by_location_id(location.id)
end

例如,如果您需要添加位置,请在控制器@company.locations << @location中使用它,Rails会处理其他事情。由于您已经声明了Company模型和Location之间的关联,因此您无需手动编写辅助函数来完成此工作。