another attempt at nested mass assignment (pluginized)

After reading previous discussions on the topic ([1] and [2]), I have
tried to take the best ideas and create a working plugin that adds
nested mass assignment to ActiveRecord. Please see
http://github.com/cainlevy/nested_assignment/tree/master.

My paradigm parameters are:

  {
    # singular associations
    :avatar_params => {
      :id => '7',
      :name => 'mugshot.jpg'
    },

    # plural associations
    :tasks_params =>
      {
        # create
        '1' => { :name => "Baz" },
        # update
        '2' => { :id => '3', :name => "Foo" },
        # destroy
        '3' => { :id => '5', :name => "Bar", :_delete => '1'}
      }
  }

Ryan, I don't believe this is on http://gist.github.com/10793.

There is one failing test for this setup because of a limitation with
using #build for a has_one association (which I've started a separate
discussion about[3]). The plugin's tests are in sqlite3 :memory:, so
they should be pretty easy to set up and run.

So the question is: what's missing? How could this be improved?

-Lance

[1]http://groups.google.com/group/rubyonrails-core/browse_thread/
thread/4049b4b313fa8be2
[2]http://groups.google.com/group/rubyonrails-core/browse_thread/
thread/3c61e00916c365e5/f0a19fc01d0246fc
[3]http://groups.google.com/group/rubyonrails-core/browse_thread/
thread/18cf8b059f5ded4a

Hi Lance,

It's great to see more attention brought to this subject. I would love
to work on this more but at the moment I do not have the time. It
would be nice if something like this could get in core for Rails 2.3.

Ryan, I don't believe this is onhttp://gist.github.com/10793.

The gist isn't intended to address singular associations or deletions.
Without that your approach looks similar to #4. Are there other
significant differences?

Also, have you tried implementing a multi-model form with this plugin?
You can fork my complex-form-examples project on GitHub and create
your own branch for this.

http://github.com/ryanb/complex-form-examples/tree/master

Thanks for your work on this,

Ryan

Hey, this turned out alright!

http://github.com/cainlevy/complex-form-examples/tree/cainlevy

Some notes on my implementation:
* I made a point to show that everything works without JavaScript. But
it would be easy to sprinkle some JS in to hide the template row and
clone it for "add another" functionality. The hardest part would be
generating a unique id and inserting it into the field names, but that
seems doable.
* Improved form helpers could clean this up a lot. I assume that's
doable in a different iteration.
* I decided to recast the "delete" checkbox as a "keep" checkbox.
That's not necessary though. What's necessary is that the template row
will by default be deleted on submit, unless the user indicates
otherwise. I just like the semantics of checking a box to *keep* the
record instead of to delete the record.

As for the gist, my paradigm parameters appear to be different from #4
in that they use a suffixed hash key (:tasks_params instead
of :tasks), and they indicate deletion via a :_delete key instead of
missing rows. I like the :_delete key much better for supporting non-
JS agents.

-Lance

In the past couple of days I've fixed a few issues with
nested_assignment and polished up my complex-form-examples branch. The
example implementation now comes with jQuery showing how the basic and
functional HTML-only form can be dressed up for an improved
experience. Comments are appreciated. I'm feeling very positive about
this approach at the moment.

-Lance

Hi Lance,

Looks good. From a brief browse through the code I have a couple
suggestions.

- The _edit_task partial could use some cleaning up. I believe using
fields_for will help a lot in this area. Check out my other branches
for examples.
- Regarding the index in JS, consider using the current (client side)
time as the index for the task when cloning it. This way it will be
unique and you don't have to worry about incrementing an index number.

Regards,

Ryan