我是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对象,但我无法弄明白。请帮忙!
答案 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之间的关联,因此您无需手动编写辅助函数来完成此工作。