Form problem with three layer deep "accepts_nested_attributes_for"

Hello,

I'm going to borrow this (http://gist.github.com/53464) example, since my model is set up exactly the same way. I'm trying to build a form that will add as many Parent to a GrandParent and as many Child to a Parent as user wants in a nested form. It work if I only have one parent and multiple children. As soon as I add more than one parent, the problem starts.

I have partials for both parent and child, where child partial gets included in the parent partial with "form.fields_for" call. In the helper, I have methods to add/remove parent or child at will. Something like this:

I thin to help you I would need to see the params that show up in the log from the post request and your controller logic which saves it.

I actually never get to that point.... This is a problem that I see on screen when I load the page before submitting the nested form.

The "Add More Parent" (and "Remove this Parent") links are created by the helper method below.

Hi,

Problem occurs when I "Add more Parent". When the next parent is added, I see one parent with mangled child form. And I think that is because the child form goes through the helper method twice - one method is the "add_parent_link" shown above and the other is "add_child_link" (not shown, but does exactly the same as "add_parent_link"). I hope I'm making sense here.

I run into the same problem.

I tried to pass an option "already_escaping" set to true if I add_parent_link is called from a partial which was already called add_parent_link. And then, I used the options like this :

         if options[:already_escaping]!=true            html = escape_javascript(html)          end

I even rewrote the escape_javascript to become "unescape_javascript" like this :

  JS_UNESCAPE_MAP = { '\\\\' => '\\', '<\/' => '</', '\n' => "\r\n", '\n' => "\n" , '\n' => "\r" , '\\"' => '"' , "\\'" => "'" }

  def unescape_javascript(javascript)     if javascript       javascript.gsub(/(\\\\|<\\\/|\\\n|\\"|\\'|\n)/) { JS_UNESCAPE_MAP [$1] }     else       ''     end   end

But still without success.

I think what's important is to understand what's beeing called and when. The children partial seems to be rendered while contructing the parent one. When it's rendered, the Javascript is escaped. And then when the parent is rendered, the Javascript is escaped once again.

Tell me if I'm wrong.

It's not a solution to the problem, but maybe seeing it from our two points of vue will help us find a solution :slight_smile:

The methods in my helper are like this :

  def helper_remove_link(fields)       out = ''       out << fields.hidden_field(:_delete)       out << link_to_function("Supprimer", "$(this).up('.# {fields.object.class.name.underscore}').hide(); $(this).previous ().value = '1'")       out   end

  def helper_add_record_link(form_builder, method, caption, options = {})

     options[:object] ||= form_builder.object.class.reflect_on_association(method).klass.new      options[:partial] ||= method.to_s.singularize      options[:form_builder_local] ||= :f      options[:insert] ||= method

     link_to_function(caption) do |page|        form_builder.fields_for(method, options[:object], :child_index => 'NEW_RECORD') do |f|          html = render(:partial => options[:partial], :locals => { options[:form_builder_local] => f })

         if options[:already_escaping]!=true            html = escape_javascript(html)          end

         page << %{                $('#{options[:insert]}').insert({                    bottom: '#{html}'.replace(/NEW_RECORD/g, new Date ().getTime())                  });                }        end      end    end

And I call the helper like this, to add a children :

  <%= helper_add_record_link f, :contacts, 'Ajouter un contact...',                   :insert => "#{prefix}contacts_#{f.object.id ? f.object.id : 'NEW_RECORD' }",                   :already_escaping => true %>

Best regards,

Christian

Hey guys,

did you find a working solution? Currently I am stuck with the same escaping problem.

Regards,

Mike