我正在尝试通过创建一个非常简单的应用程序来学习 Rails,该应用程序只是创建一个网站,人们可以在该网站上创建一个作者和书籍列表,并与该书由作者撰写的关联。我希望这会简单而干燥,但我遇到了意想不到的麻烦。
首先查看我的模型,我已经建立了关联并制作了所需的每个数据点(author.name、book.title 和 book.author)。我不想将 :author 或 :author_id 添加到 attr_accessible 列表中,因为我想使用适当的 Rails 约定。
应用程序/模型/作者.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 中的值添加了一个选择字段。
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 方法。我尝试保存基本参数并从所选作者创建作者关联。
应用程序/控制器/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关联?