Search code examples
ruby-on-railshamlsimple-formnested-formscocoon-gem

Rails circular and dynamic nested form


I'm trying to create a 'blog' example with a circular and dynamic nested form, but I can't make it work, it just keeps loading forever and I need to kill the server in order to stop it.

A blog has comments, and a comment has comments. That's all.

Please help me :)

I'm using:

  • rails (5.1.6)
  • activerecord (5.1.6)
  • simple_form (3.5.1)
  • cocoon (1.2.11)
  • jquery-rails (4.3.1)
  • haml (5.0.4)

blog.rb

class Blog < ApplicationRecord
  validates :message, presence: true

  has_many :comments, inverse_of: :blog

  accepts_nested_attributes_for :comments,
    allow_destroy: true,
    reject_if: ->(attributes) {attributes[:text].blank?}
end

comment.rb

class Comment < ApplicationRecord
  belongs_to :blog, inverse_of: :comments, optional: true
  belongs_to :comment, optional: true
  has_many :comments, inverse_of: :comment

  accepts_nested_attributes_for :comments,
    allow_destroy: true,
    reject_if: ->(attributes) {attributes[:text].blank?}
end

form.html.haml

= simple_form_for blog do |f|
  = f.input :message

  .comments
    = f.simple_fields_for :comments do |comment|
      = render 'comment_fields', f: comment

  = link_to_add_association 'Add', f, :comments, data: {association_insertion_node: '.comments', association_insertion_method: :append}

  = f.button :submit

_comment_fields.html.haml

.nested-fields.ml-3
  = link_to_remove_association 'Remove', f

  = f.input :text

  = f.simple_fields_for :comments do |sub_comment|
    = render 'comment_fields', f: sub_comment

= link_to_add_association 'Add', f, :comments, data: {association_insertion_node: '.comments', association_insertion_method: :append}

I also tried with the Railscasts example, and it didn't work because the link_to_add_fields helper loads the comment_fields file and it has the link_to_add_fields inside.


Solution

  • Well... it's an issue with the cocoon gem. I found a possible (and dirty) solution, if I limit the nesting, it works.

    .nested-fields.ml-3
      = f.input :text
    
      - index ||= 0
      - index += 1
      - if index < 10
        = link_to_add_association 'Add', f, :comments, data: {association_insertion_method: :append}, render_options: {locals: {index: index}}
    
      = link_to_remove_association 'Remove', f
    
      = f.simple_fields_for :comments do |sub_comment|
        = render 'comment_fields', f: sub_comment