我有一个使用“has_many :through”关系的 Rails 应用程序。我有 3 个表/模型。它们是 Employee、Store 和 StoreEmployee。一名员工可以为一家或多家商店工作。在 Store 视图 (show.html.erb) 上,我想包含一个表单以将员工添加到商店。如果员工尚不存在,则将其添加到员工表中。如果它已经存在,它只是被添加到存储中。
以下是模型定义:
# models
class Employee < ActiveRecord::Base
has_many :store_employees
has_many :stores, :through => :store_employees
attr_accessible :email, :name
end
class Store < ActiveRecord::Base
has_many :store_employees
has_many :employees, :through => :store_employees
attr_accessible :address, :name
end
class StoreEmployee < ActiveRecord::Base
belongs_to :store
belongs_to :employee
attr_accessible :employee_id, :store_id
end
使用 rails 控制台,我可以证明数据模型工作正常,如下所示:
emp = Employee.first
str = Store.first
str.employees << emp # add the employee to the store
str.employees # shows the employees that work at the store
emp.stores # shows the stores where the employee works
我还更新了我的 routes.rb 以将 employees 资源嵌套在 stores 资源下,如下所示:
resources :stores do
resources :employees
end
编辑:我还将资源 :employees 添加为“未嵌套”资源。所以现在看起来像这样:
resources :stores do
resources :employees
end
resources :employees
所以,在 store 控制器的 show 动作中,我认为它应该是这样的:
def show
@store = Store.find(params[:id])
@employee = @store.employees.build # creating an empty Employee for the form
respond_to do |format|
format.html # show.html.erb
format.json { render json: @store }
end
end
这是商店的 show.html.erb,包括添加员工的表单:
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= @store.name %>
</p>
<p>
<b>Address:</b>
<%= @store.address %>
</p>
<%= form_for([@store, @employee]) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.submit "Add Employee" %>
<% end %>
<%= link_to 'Edit', edit_store_path(@store) %> |
<%= link_to 'Back', stores_path %>
单击“添加员工”按钮时,我收到此错误消息:
EmployeesController#create 中的 NoMethodError
# 未定义的方法`employee_url'
那么,我错过了什么?我认为这与“form_for”有关,但我不确定。我不知道为什么EmployeesController#create 被调用。我对 routes.rb 做错了吗?
我不知道添加员工的逻辑应该去哪里。在员工控制器中?存储控制器?
### 更新这是EmployeesController 中更新的create 方法。我包括了米沙回答中的建议。
def create
@store = Store.find(params[:store_id])
@employee = @store.employees.build(params[:employee])
respond_to do |format|
if @employee.save
format.html { redirect_to @store, notice: 'Employee was successfully created.' }
format.json { render json: @employee, status: :created, location: @employee }
else
format.html { render action: "new" }
format.json { render json: @employee.errors, status: :unprocessable_entity }
end
end
end
进行此更改后,我成功保存了 Employee,但未创建 store_employees 关联记录。我不知道为什么。这是创建记录时我的终端中的输出。请注意,商店是 SELECTed 并且 Employee 是 INSERTed ,但仅此而已。任何地方都没有 store_employees 记录:
Started POST "/stores/1/employees" for 127.0.0.1 at 2012-10-10
13:06:18 -0400 Processing by EmployeesController#create as HTML
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"LZrAXZ+3Qc08hqQT8w0MhLYsNNSG29AkgCCMkEJkOf4=",
"employee"=>{"name"=>"betty", "email"=>"betty@kitchen.com"},
"commit"=>"Add Employee", "store_id"=>"1"} Store Load (0.4ms)
SELECT "stores".* FROM "stores" WHERE "stores"."id" = ? LIMIT 1
[["id", "1"]] (0.1ms) begin transaction SQL (13.9ms) INSERT
INTO "employees" ("created_at", "email", "name", "updated_at") VALUES
(?, ?, ?, ?) [["created_at", Wed, 10 Oct 2012 17:06:18 UTC +00:00],
["email", "betty@kitchen.com"], ["name", "betty"], ["updated_at", Wed,
10 Oct 2012 17:06:18 UTC +00:00]] (1.3ms) commit transaction
Redirected to http://localhost:3000/stores/1 Completed 302 Found in
23ms (ActiveRecord: 15.6ms)