嵌套表单中的嵌套表单 - Cocoon Gem:第 3 级 child 不保存 - Rails 5

Nested form inside of a nested form - Cocoon Gem: 3rd level child doesn't save - Rails 5

花了几个小时试图研究解决方案,发现了一些非常相似的问题 like this one, or ,尽管所有建议的修复都没有解决我的问题:

正在尝试使用 Cocoon Gem 在嵌套表单内部构建嵌套表单,但第 3 级 child 不会保存到数据库中。

模型结构非常简单,只有 "has_many / belongs_to" 个关系:

一个文本有很多引用。一个引用有很多评论。

实现中的动态 UI 交互有效,添加和删除字段有效,不幸的是,尽管只保存文本和引号,而不保存评论。没有显示错误。

表格如下:

_text_form.html.erb

<%= form_for(@text, html: { multipart: true }) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="field">
    <%= f.text_field :title, placeholder: "Enter Title" %>      
  </div>
  <div>
      <h3>Quotes:</h3>
      <div id="quotes">
        <%= f.fields_for :quotes do |quote| %>
          <%= render 'quote_fields', f: quote %>
        <% end %>

        <div class="links">
          <%= link_to_add_association 'add quote', f, :quotes, class: "btn btn-default" %>
        </div>
      </div>
  </div>

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

_quote_fields.html.erb

<div class="nested-fields">
  <%= f.text_area :content, placeholder: "Compose new quote..." %>
  <span class="picture">
    <%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
  </span>

  <div>
      <h3>Comments:</h3>
      <div id="comments">
        <%= f.fields_for :comments do |comment| %>
          <%= render 'comment_fields', f: comment %>
        <% end %>
        <div class="links">
          <%= link_to_add_association 'add comment', f, :comments, class: "btn btn-default" %>
        </div>
      </div>
  </div>
  <div class="links">
    <%= link_to_remove_association "remove quote", f, class: "btn btn-default" %>
  </div>
</div>

<script type="text/javascript">
  $('#quote_picture').bind('change', function() {
    var size_in_megabytes = this.files[0].size/1024/1024;
    if (size_in_megabytes > 2) {
      alert('Maximum file size is 2MB. Please choose a smaller file.');
    }
  });
</script>

_comment_fields.html.erb

<div class="nested-fields">
  <%= f.text_area :bodycomment, placeholder: "Write a comment..." %>
  <%= link_to_remove_association "remove comment", f, class: "btn btn-default" %>
</div>

以下是模型:

text.rb

class Text < ApplicationRecord
  belongs_to :user, inverse_of: :texts
  has_many :quotes, dependent: :destroy, inverse_of: :text
  has_many :comments, :through => :quotes
  accepts_nested_attributes_for :quotes, reject_if: :all_blank, allow_destroy: true
  accepts_nested_attributes_for :comments, reject_if: :all_blank, allow_destroy: true
  default_scope -> { order(created_at: :desc) }
  mount_uploader :coverimage, CoverimageUploader

  validates :user_id, presence: true
  validates :title, presence: true
  validate :coverimage_size

  private

      # Validates the size of an uploaded picture.
      def coverimage_size
        if coverimage.size > 5.megabytes
          errors.add(:coverimage, "should be less than 5MB")
        end
      end

end

quote.rb

class Quote < ApplicationRecord
  belongs_to :text, inverse_of: :quotes
  has_many :comments, dependent: :destroy, inverse_of: :quote
  accepts_nested_attributes_for :comments, reject_if: :all_blank, allow_destroy: true

  mount_uploader :picture, PictureUploader
  validates :content, presence: true, length: { maximum: 350 }
  validate :picture_size

private

  #Validates size of image upload
  def picture_size
    if picture.size > 2.megabytes
      errors.add(:picture, "should be less than 2MB")
    end
  end

end

comment.rb

class Comment < ApplicationRecord
  belongs_to :quote, inverse_of: :comments
  validates :quote_id, presence: true
  validates :bodycomment, presence: true

end

这里是控制器:

quotes_controller.rb

class QuotesController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy


  def show
  end



  def create
    @quote = current_user.quotes.build(quote_params)
   if @quote.save
     flash[:success] = "Quote created!"
     redirect_to root_url
   else
     @feed_items = []
     render 'static_pages/home'
   end
  end

  def destroy
    @quote.destroy
    flash[:success] = "Quote deleted"
    redirect_to request.referrer || root_url
  end


  private

     def quote_params
       params.require(:quote).permit(:content, :picture, comments_attributes: [:id, :bodycomment
         , :_destroy])
     end

     def correct_user
       @quote = current_user.quotes.find_by(id: params[:id])
       redirect_to root_url if @quote.nil?

     end

end

comments_controller.rb

class CommentsController < ApplicationController
before_action :logged_in_user, only: [:create, :edit, :update, :destroy]
before_action :correct_user, only: :destroy


    def show
    end

    def create
        @comment = current_user.comments.build(comment_params)
        if @comment.save
          flash[:success] = "Comment created!"
          redirect_to root_url
        else
          @feed_items = []
          render 'static_pages/home'
        end
      end

    def destroy
      @comment.destroy
      flash[:success] = "Comment deleted"
      redirect_to request.referrer || root_url
    end

    private

    def comment_params
          params.require(:comment).permit(:bodycomment)
    end

    def correct_user
      @comment = current_user.comments.find_by(id: params[:id])
      redirect_to root_url if @comment.nil?

    end

end

想知道是不是 javascript 问题...

非常感谢您对此进行调查。非常感谢,感谢您的帮助。

编辑

这里是texts_controller.rb

class TextsController < ApplicationController
  before_action :logged_in_user, only: [:create, :edit, :update, :destroy]
  before_action :correct_user, only: :destroy
  before_action :find_text, only: [:show, :edit, :update, :destroy]


  def show
  end

  def new
    @text = current_user.texts.build
  end

  def create
    @text = current_user.texts.build(text_params)
    if @text.save
     flash[:success] = "Text created!"
     render 'show'
    else
     render 'static_pages/home'
    end
  end


  def edit
  end

  def update
    if @text.update(text_params)
      redirect_to root_url
    else
      render 'edit'
    end
  end

  def destroy
    @text.destroy
    flash[:success] = "Text deleted"
    redirect_to request.referrer || root_url
  end

  private

    def text_params
    params.require(:text).permit(:url, :title, :coverimage,
                                  :publication, :author, :summary, quotes_attributes: [:id, :content, :picture, :_destroy], comments_attributes: [:id, :bodycomment, :_destroy])
    end

    def find_text
        @text = Text.find(params[:id])
      end

    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end

end

以下是我在保存表单字段后获得的一些日志信息:

--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  utf8: "✓"
  authenticity_token: NQLh7TwlhfbV4ez91HGMyYZK6YYYiLXhHG/cAhrAsRylIAuFFhjnKX0vEO8ZIVbsxGES3byBgUMz21aSOlGiqw==
  text: !ruby/object:ActionController::Parameters
    parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
      title: Title of the Book
      quotes_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
        '1490626822148': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
          content: This is a quote from the book.
          _destroy: 'false'
          comments_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
            '1490626833771': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
              bodycomment: Here is a comment on the quote of the book.
              _destroy: 'false'
    permitted: false
  commit: Create Text
  controller: texts
  action: create
permitted: false 

这里是终端的日志文件:

Started POST "/texts" for ::1 at 2017-03-27 17:00:51 +0200
Processing by TextsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"NQLh7TwlhfbV4ez91HGMyYZK6YYYiLXhHG/cAhrAsRylIAuFFhjnKX0vEO8ZIVbsxGES3byBgUMz21aSOlGiqw==", "text"=>{"title"=>"Title of the Book", "publication"=>"", "author"=>"", "url"=>"", "summary"=>"", "quotes_attributes"=>{"1490626822148"=>{"content"=>"This is a quote from the book.", "_destroy"=>"false", "comments_attributes"=>{"1490626833771"=>{"bodycomment"=>"Here is a comment on the quote of the book.", "_destroy"=>"false"}}}}}, "commit"=>"Create Text"}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
Unpermitted parameter: comments_attributes
   (0.1ms)  begin transaction
  SQL (0.7ms)  INSERT INTO "texts" ("user_id", "url", "title", "publication", "author", "summary", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?)  [["user_id", 1], ["url", ""], ["title", "Title of the Book"], ["created_at", 2017-03-27 15:00:51 UTC], ["updated_at", 2017-03-27 15:00:51 UTC]]
  SQL (0.4ms)  INSERT INTO "quotes" ("content", "created_at", "updated_at", "text_id") VALUES (?, ?, ?, ?)  [["content", "This is a quote from the book."], ["created_at", 2017-03-27 15:00:51 UTC], ["updated_at", 2017-03-27 15:00:51 UTC], ["text_id", 366]]
   (1.3ms)  commit transaction
  Rendering texts/show.html.erb within layouts/application
  Quote Load (0.2ms)  SELECT "quotes".* FROM "quotes" WHERE "quotes"."text_id" = ?  [["text_id", 366]]
  Rendered texts/show.html.erb within layouts/application (5.8ms)
  Rendered layouts/_shim.html.erb (0.5ms)
  Rendered layouts/_header.html.erb (1.4ms)
  Rendered layouts/_footer.html.erb (1.8ms)
Completed 200 OK in 127ms (Views: 100.1ms | ActiveRecord: 3.1ms)
  1. 型号... text.rb ...我不得不输入 accepts_nested_attributes_for :comments ...除了已经发布的
  2. TextController ...您的嵌套允许参数需要出现在这里,.permit(:content, :picture, quotes_attributes: [:id, :content, :picture, :_destroy, comments_attributes: [:id, :bodycomment, :_destroy]])

我可能把变量名去掉了一点(尤其是你没有列出的 TextController),但基本上,看起来你正试图通过其他控制器继承嵌套——当唯一的控制器被调用时是文本控制器。

可以肯定的是,在第二个控制台中放置 tail -f log/<logname> 或在执行 save/update 时查看终端控制台以观察许可问题。

如果还有问题,请告诉我!

...基于新控制器的更新

控制器需要调整(您现在有一个']'放错了地方)。

params.require(:text).permit(:url, :title, :coverimage,
                                  :publication, :author, :summary, quotes_attributes: [:id, :content, :picture, :_destroy, comments_attributes: [:id, :bodycomment, :_destroy]])

在您也修复模型之前,这将不起作用...

accepts_nested_attributes_for :comments