嵌套形式内部的嵌套形式 - Cocoon Gem:三级小孩不会保存 - Rails 5

时间:2017-03-24 23:51:14

标签: javascript ruby-on-rails ruby-on-rails-5 nested-forms cocoon-gem

尝试研究解决方案几个小时后,发现了一些非常类似的问题like this onethis one,但所有提议的修复都无法解决我的问题:

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

非常简单的模型结构,只有" 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 个答案:

答案 0 :(得分:3)

  1. 模特...... text.rb ......除了已发布的
  2. 之外,我还要加入accepts_nested_attributes_for :comments ...
  3. TextController ...你的嵌套允许参数需要在这里发生,.permit(:content, :picture, quotes_attributes: [:id, :content, :picture, :_destroy, comments_attributes: [:id, :bodycomment, :_destroy]])
  4. 我可能关闭变量名(特别是你没有列出的TextController),但基本上,看起来你试图通过其他控制器继承嵌套 - 当被调用的唯一控制器是TextController。

    确保在执行保存/更新以查看许可证问题时,将tail -f log/<logname>放入第二个控制台或查看终端控制台。

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

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

    需要调整控制器(你现在有一个错位的']'。

    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