我正在嘗試通過創建一個非常簡單的應用程序來創建一個網站,在這個應用程序中有人可以創建一個作者列表和一本書由作者編寫的關聯書籍。我希望這會很簡單,乾燥,但我一直有一個意想不到的麻煩。如何選擇適當的Association in Rails?
首先看我的模型,我已經建立了關聯,並且要求每個數據點(author.name,book.title和book.author)。我不想在attr_accessible列表中添加:author或author_id,因爲我想使用適當的Rails約定。
應用程序/模型/ 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
書籍控制器和視圖我想正是從腳手架和非常無趣。有趣的是書籍控制器。看着新的方法,我所做的只是添加一個收集器,該收集器使用ID將作者名稱數組傳遞給視圖。 (老實說,我認爲我寧願不通過ID在所有。)
應用程序/控制器/ 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中的值添加了一個選擇字段。
應用程序/視圖/書籍/ _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'
最後,回到我的控制器的創建方法。我嘗試保存基本參數並從所選作者創建作者關聯。
應用程序/控制器/ 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 [:book]而不是params [:author]。所以我有兩個問題。
1)我該如何解決我的select語句讓它以params [:author]而不是params [:book]發送?
2)有沒有更好的方法來做到這一點,完全隱藏ID協會?
糟糕,我想我可以使用label_tag:作者。 – Geoff
我最終將控制器更改爲'@book = Book.new(params [:book])'和'@book.author = Author.find_by_name(params [:author])''。這有點容易閱讀,不會導致大量屬性警告,並確保我有一個'@ book',如果因爲錯誤需要重新渲染,可能會出現錯誤標記。 – Geoff