1

私は非常に単純なアプリケーションを作成することで 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 関連付けを完全に隠す、これを行うためのさらに良い方法はありますか?

4

2 に答える 2

0

私はほとんどそれを理解したと思います、そして私が疑ったように、私は私のモデルコードを全く変更する必要はありませんでした。

コントローラの@authorsの新しいメソッド定義を変更して、次のような作成者名のみを返すようにしました。

@authors = Author.pluck(:name)

これにより、idを非表示にするという私の目標は達成されましたが、コントローラーのcreateメソッド(下記)でidの代わりに名前で検索する必要がある場合はおそらく少し遅くなります。

次に、ビューを修正して、params [:book] [:author]ではなくparams [:author]を設定しました。

= label :author, :name, 'Author'
= select_tag(:author, options_for_select(@authors), {:include_blank => ""})

最後に、@bookの新しいメソッド作成を変更しました。

@book = Author.find_by_name(params[:author]).books.create(params[:book])

私はこれにかなり満足しています。私が本当に好きではない唯一のことは、ラベルが単に「作成者」ではなく「作成者名」ラベルを作成することです。

于 2012-10-25T15:17:30.947 に答える
0

「保護された属性を一括割り当てできません: 作成者」は、属性がモデルで attr_accessible としてリストされていないことを意味します

于 2012-10-24T21:58:59.740 に答える