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