我正在使用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 %>
是否可以将另一个资源嵌套到已创建的资源中,以便在图书创建页面中添加作者创建?
答案 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 :author
,Book
的{{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)
答案 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;相关作者记录也是