私は非常に単純なアプリケーションを作成することで Rails を学ぼうとしています。このアプリケーションは、誰かが著者と本のリストを作成し、その本が著者によって書かれたものであるという関連付けを作成できる Web サイトを作成するだけです。これがシンプルで DRY であることを望んでいましたが、予想外の量の問題が発生しました。
まず自分のモデルを見て、関連付けを設定し、必要なすべてのデータ ポイント (author.name、book.title、および book.author) を作成しました。適切な Rails 規則を使用したいので、:author または :author_id を attr_accessible リストに追加したくありません。
app/models/author.rb:
class Author < ActiveRecord::Base
attr_accessible :name
validates_presence_of :name
has_many :books
end
アプリ/モデル/book.rb:
class Book < ActiveRecord::Base
attr_accessible :title
validates_presence_of :title
belongs_to :author
validates_associated :author
end
私が思う本のコントローラーとビューは、まさに足場からのものであり、非常に面白くありません。興味深いのは、books コントローラーです。新しいメソッドを見ると、作成者名と ID の配列を取得してビューに渡すコレクターを追加するだけでした。(正直なところ、IDをまったく渡さない方がいいと思います。)
app/controllers/books_controller.rb
# GET /books/new
# GET /books/new.json
def new
@book = Book.new
@authors = Author.all.collect {|a| [a.name, a.id]}
respond_to do |format|
format.html # new.html.erb
format.json { render json: @book }
end
end
ビューについては、デフォルトの new.html.haml を使用しましたが、_form.html.haml に変更を加えました。@authors の値を使用して選択フィールドを追加しました。
app/views/books/_form.html.haml
= form_for @book do |f|
- if @book.errors.any?
#error_explanation
%h2= "#{pluralize(@book.errors.count, "error")} prohibited this book from being saved:"
%ul
- @book.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name
= f.text_field :name
.field
= f.label :author
= f.select(:author, @authors, {:include_blank => ""})
.actions
= f.submit 'Save'
最後に、create メソッドのコントローラーに戻ります。基本パラメータを保存し、選択した著者から著者の関連付けを作成しようとしています。
app/controllers/books_controller.rb
# POST /books
# POST /books.json
def create
@book = Book.new(params[:book])
@book.author = Author.find_by_id(params[:author])
respond_to do |format|
if @book.save
format.html { redirect_to @book, notice: 'Book was successfully created.' }
format.json { render json: @book, status: :created, location: @book }
else
format.html { render action: "new" }
format.json { render json: @book.errors, status: :unprocessable_entity }
end
end
end
[保存] をクリックすると、次のエラーが表示されます。
Can't mass-assign protected attributes: author
これは、選択した値が params[:author] ではなく params[:book] に入れられたためだと理解しています。そこで、質問が 2 つあります。
1) params[:book] の代わりに params[:author] で送信するように select ステートメントを修正するにはどうすればよいですか?
2) ID 関連付けを完全に隠す、これを行うためのさらに良い方法はありますか?