【问题标题】:Incorrect HTML when pre-populating nested forms in Rails 5.1在 Rails 5.1 中预填充嵌套表单时 HTML 不正确
【发布时间】:2017-11-19 10:17:29
【问题描述】:

我有一个使用 Google Books API 的 Rails 5.1 应用程序,我需要在表单中预填充嵌套字段。有两种方法可以创建Book

首先,通过普通的/books/new 形式,其中accepts_nested_attributes_for :authorshas_many: through 关联。我在这里使用cocoon gem,一切正常。

其次,用户可以通过使用 ISBN 号搜索 Google Books API 来创建Book。然后,此数据在提交到BooksController 中的create 操作之前预填充表单。除了能够正确提交嵌套的Author 数据之外,我还成功地完成了这项工作。

我目前让每个作者在表单中填充一个字段,但是当我提交数据时,只有作者数组中的最后一项(如果一本书有多个作者)被保存。

我相信这是因为表单 html 的两个字段具有相同的 nameid,如下所示。我如何获得此表格以提交两位作者?

<input value="John J. Ratey" type="text" name="book[authors_attributes][0][name]" id="book_authors_attributes_0_name">
<input value="Richard Manning" type="text" name="book[authors_attributes][0][name]" id="book_authors_attributes_0_name">

books_controller.rb

class BooksController < ApplicationController

before_action :authenticate_user!
before_action :set_book, except: [:index, :new, :create, :new_book, :submit_book]

def create
    @book = current_user.books.create(book_params)
    @book.authors.each {|author| author.user_id = current_user.id}

    if @book.save
        redirect_to book_path(@book)
    else
        render :new
    end
end

def new_book
end

def submit_book
    @book = Book.new
    @book.authors.new
    @response = GoogleBooks.new(params[:q], @book)
end

private

    def set_book
        @book = Book.find(params[:id])
    end

    def book_params
        params.require(:book).permit(:title, :subtitle, :description, author_ids:[], authors_attributes: [:id, :name, :_destroy])
    end

end

book.rb

class Book < ApplicationRecord
  has_many :book_authors
  has_many :authors, through: :book_authors

  accepts_nested_attributes_for :authors, allow_destroy: true

  validates :title, presence: true
  validates_associated :authors
end

google_books.rb

class GoogleBooks
  include HTTParty
  base_uri 'https://www.googleapis.com/books/v1'

  def initialize(isbn, book)
    @query = self.class.get("/volumes?q=isbn:#{isbn}")
    @book = book
  end

  def title
    @query['items'].first['volumeInfo']['title']
  end

  def subtitle
    @query['items'].first['volumeInfo']['subtitle']
  end

  def description
    @query['items'].first['volumeInfo']['description']
  end

  def authors
    @query['items'].first['volumeInfo']['authors']
    #=> ['John J. Ratey', 'Richard Manning']
  end

end

submit_book.html.erb

<%= form_for @book do |f| %>
  <%= f.text_field :title, value: @response.title %>
  <%= f.text_field :subtitle, value: @response.subtitle %>
  <%= f.text_field :description, value: @response.description %>

  <%= f.fields_for :authors, @book.authors.build do |authors_fields| %>
    <% @response.authors.each do |author| %>
      <%= authors_fields.text_field :name, value: author %>
    <% end %>
  <% end %>

<%= f.submit %>

【问题讨论】:

  • 你能在 id 后面加上 [] 吗?
  • @Psi 你能详细说明你的意思吗?

标签: html ruby-on-rails ruby nested-forms


【解决方案1】:

解决了。

是一个改变的案例

<%= f.fields_for :authors, @book.authors.build do |authors_fields| %>
  <% @response.authors.each do |author| %>
    <%= authors_fields.text_field :name, value: author %>
  <% end %>
<% end %>

到这里

<% @response.authors.each do |author| %>
  <%= f.fields_for :authors, @book.authors.build do |authors_fields| %>
    <%= authors_fields.text_field :name, value: author %>
  <% end %>
<% end %>

这会产生以下正确的 HTML:

<input value="John J. Ratey" type="text" name="book[authors_attributes][0][name]" id="book_authors_attributes_0_name">
<input value="Richard Manning" type="text" name="book[authors_attributes][1][name]" id="book_authors_attributes_1_name">

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多