在创建帖子时,如何将rails资源嵌套在另一个资源中?

时间:2014-08-11 09:22:55

标签: ruby-on-rails ruby ruby-on-rails-4 nested-attributes

我正在使用rails构建一个书库,我需要能够在书籍创建表单中添加作者,一旦添加了书籍,就会将作者帖子传递给作者列表。在同一本书创建资源中,我已经在book.rb文件和author.rb文件中创建了has_many:authors,我创建了belongs_to:author,并且工作正常我可以选择作者可能创建的书籍。以下设置:

book.rb

class Book < ActiveRecord::Base

    has_attached_file :jacket_cover, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
    validates_attachment_content_type :jacket_cover, :content_type => /\Aimage\/.*\Z/

    validates :jacket_cover, :title, :synopsis, :body, presence: true

    belongs_to :author

    scope :available, ->{ where(available: true) }
    scope :unavailable, ->{ where(available: [nil, false]) }

end

author.rb

class Author < ActiveRecord::Base
    has_many :books
end

books_controller.rb

class BooksController < ApplicationController
  before_action :set_book, only: [:show, :edit, :update, :destroy]

  def index
    @books = Book.all
  end


  def show
  end

  # GET /books/new
  def new
    @book = Book.new
  end

  # GET /books/1/edit
  def edit
  end

  def create
    @book = Book.new(book_params)

    respond_to do |format|
      if @book.save
        format.html { redirect_to @book, notice: 'Book was successfully created.' }
        format.json { render action: 'show', status: :created, location: @book }
      else
        format.html { render action: 'new' }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @book.update(book_params)
        format.html { redirect_to @book, notice: 'Book was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @book.destroy
    respond_to do |format|
      format.html { redirect_to books_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_book
      @book = Book.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def book_params
      params.require(:book).permit(:title, :synopsis, :body, :jacket_cover)
    end
end

authors_controller.rb

class AuthorsController < ApplicationController
  before_action :set_author, only: [:show, :edit, :update, :destroy]
  def index
    @authors = Author.all
  end
  def show

  end
  def new
    @author = Author.new
  end

  # GET /authors/1/edit
  def edit
  end
  def create
    @author = Author.new(author_params)

    respond_to do |format|
      if @author.save
        format.html { redirect_to @author, notice: 'Author was successfully created.' }
        format.json { render action: 'show', status: :created, location: @author }
      else
        format.html { render action: 'new' }
        format.json { render json: @author.errors, status: :unprocessable_entity }
      end
    end
  end
  def update
    respond_to do |format|
      if @author.update(author_params)
        format.html { redirect_to @author, notice: 'Author was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @author.errors, status: :unprocessable_entity }
      end
    end
  end
  def destroy
    @author.destroy
    respond_to do |format|
      format.html { redirect_to authors_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_author
      @author = Author.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def author_params
      params.require(:author).permit(:name, :biography, :books_ids => [] )
    end
end

这允许我创建好书的书籍和作者,但我现在希望将作者创作嵌入到我的书中创建。

图书创建表单

<%= simple_form_for(@book, :html => { :multipart => true }) do |f| %>
  <%= f.error_notification %>

  <div class="inputs">
    <%= f.file_field :jacket_cover %>
    <%= f.input :title %>
    <%= f.input :synopsis %>
    <%= f.input :body %>
  </div>

  <div class="actions">
    <%= f.button :submit %>
  </div>
<% end %>

作者创建表单

<%= simple_form_for(@author) do |f| %>
  <%= f.error_notification %>

  <div class="inputs">
    <%= f.input :name %>
    <%= f.association :books, 
                     as: :check_boxes, 
                     value_method: :id,
                     label: 'Books' %>
    <%= f.input :biography %>
  </div>

  <div class="actions">
    <%= f.button :submit %>
  </div>
<% end %>

是否可以将另一个资源嵌套到已创建的资源中,以便在图书创建页面中添加作者创建?

4 个答案:

答案 0 :(得分:2)

是的,您需要为simple_form_for提供 accepts_nested_attributes_for simple_fields_for 帮助器(正如您使用{{1}一样})

第1步

simple_form_for模型中,您应添加Book

第2步

修改books_controller.rb的新方法

如果accepts_nested_attributes_for :author模型中有belongs_to :authorBook的{​​{1}}方法将

new

第3步

您的BooksController方法应修改为

def new
@book = Book.new
@book.build_author #This is very important
end

第4步

最后,您book_params的{​​{1}}将是这样的

def book_params
params.require(:book).permit(:title, :synopsis, :body, :jacket_cover,author_attributes: [:name,:biography,..,..])
end

答案 1 :(得分:1)

  

是否可以将另一个资源嵌套到已创建的资源中,以便在图书创建页面中添加作者创建?

你可能想要一个比这更长的答案。

您需要排除nested attributes

答案 2 :(得分:1)

在书籍模型中:

 has_one :author, dependent: :destroy
  accepts_nested_attributes_for :authors

在BooksController中:new添加行

 @book = Author.new
 @book.build_author

@book

的形式
<%= form_for(@book, :html => { :multipart => true }) do |f| %>
  <%= f.error_notification %>
  <div class="inputs">
#book fields
  </div>
  <%= f.fields_for :author do |author| %>
#author fields
    <%= f.button :submit %>
  </div>
<% end %>

不要忘记修改book_params方法,如Rich Peck的回答所示。

答案 3 :(得分:0)

你的问题有点冗长,但我会详细说明你需要知道的事情

-

嵌套对象

  

是否可以将另一个资源嵌套到已创建的资源中,以便在图书创建页面中添加作者?

Rails建立在Ruby(object orientated语言)之上。这意味着Rails也是面向对象的,所以如果你想在创建一本书的同时创建一个作者(这只适用于create),你就会这样做。想要为您的模型使用accepts_nested_attributes_for指令:

#app/models/book.rb
Class Book < ActiveRecord::Base
   has_one :author
   accepts_nested_attributes_for :author
end

#app/controllers/books_controller.rb
Class BooksController < ApplicationController
   def new
      @book = Book.new
      @book.build_author #-> this will be authors.build if multiple
   end

   def create
      @book = Book.new(book_params)
      @book.save
   end

   private

   def book_params
      params.require(:book).permit(:title, :synopsis, :body, author_attributes: [:biography])
   end
end

这将允许您创建以下内容(为简单起见,使用form_for):

#app/views/books/new.html.erb
<%= form_for @book do |f| %>
   <%= f.text_field :title %>
   <%= f.text_field :synopsis %>
   <%= f.text_field :body %>

   <%= f.fields_for :author do |a| %>
      <%= a.text_field :biography %>
   <% end %>

   <%= f.submit %>
<% end %>

这将创建图书记录&amp;相关作者记录也是