2

「has_many :through」関係を使用する Rails アプリがあります。私は3つのテーブル/モデルを持っています。それらは、Employee、Store、および StoreEmployee です。従業員は、1 つ以上の店舗で働くことができます。Store ビュー (show.html.erb) に、ストアに従業員を追加するためのフォームを含めたいと考えています。従業員がまだ存在しない場合は、Employees テーブルに追加されます。すでに存在する場合は、ストアに追加されます。

モデル定義は次のとおりです。

# 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 を更新して、従業員リソースを store リソースの下に次のように入れ子にしました。

resources :stores do
  resources :employees
end

編集: リソース :employees を「ネストされていない」リソースとして追加しました。そのため、次のようになります。

resources :stores do
  resources :employees
end
resources :employees

したがって、ストア コントローラーの 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

この変更を行った後、従業員は正常に保存されましたが、store_employees 関連付けレコードは作成されません。理由がわかりません。レコードを作成するときの端末の出力は次のとおりです。店舗が選択され、従業員が挿入されていることに注意してください。どこにも 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)
4

1 に答える 1

1

この問題は、EmployeesController#createメソッドの次のスニペットが原因です。

redirect_to @employee

これは を使用しようとしますemployee_urlが、ルート ファイルに employees リソースをネストしているため、存在しません。解決策は、「ネストされていない」リソースも追加することです。

resources :stores do
  resources :employees
end
resources :employees

または、単に別の場所にリダイレクトします。たとえば、 に戻りStoresController#showます。

ところで、デフォルトの scaffolding は期待どおりには機能しません。店舗に関連する従業員を作成しません。そのためには、多少書き直す必要があります。

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 @employee, 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
于 2012-10-10T15:09:52.357 に答える