Saving Multiple ActiveRecord objects at once that _aren't_ nested

It struck me today that there's no way to emulate
accepts_nested_attributes_for for saving multiple objects that aren't
nested.

accepts_nested_attributes_for gives a good pattern for managing
multiple objects in a single form, elegantly handling current records
and new records, and validations for the lot of them.

Should there be an equivalent way to manage multiple objects in a
single form that aren't nested under any parent? Something like:

@posts = Post.all

<% form_for @posts do |f| %>
  <% fields_for :post %>
    ...
  <% end %>
<% end %>

What do you think?

Paul

@posts = Post.all

<% form_for @posts do |f| %>
<% fields_for :post %>
...
<% end %>
<% end %>

What do you think?

I think most of the time the better solution here is to have an
'owning record' of some sort. For example:

<% form_for @blog ... %>

Otherwise what would go in the controller action? What would we be
calling .attributes= on?

I guess one of the use cases is a list of checkboxes, eg:

http://railscasts.com/episodes/165-edit-multiple

... but I think it holds for any list that would present multiple
non-nested objects for editing in a single form.

Ryan's implementation makes use of form_tag and a loop inside the
controller action ... which to me indicates a bit of code smell, but
also that Rails doesn't yet have an elegant solution.

Otherwise what would go in the controller action? What would we be
calling .attributes= on?

I'm not exactly sure how the best solution would work.

I'm not certain about the owning record in this case ... <%= form_for
@post ... %> doesn't express any intent that there's going to be
multiple objects in the form ( where for example, <% fields_for
:comments %> does...

It might also require a class method on active record that would
accept multiple records to create or update. Perhaps an equivalent of
find_or_create ... that would mirror the behaviour of
accepts_nested_attributes_for ... maybe something like:

Post.create_or_update_many( { '0' => { # create record... }, { '1' =>
{ # update record } } )

... another option would be to use some kind of presenter pattern ( <%
form_for @posts_collection ... %> ) to mock the owning record ... but
I've never been fully sold on presenters.

If there's interest in this I'd be happy to spin up a plugin or a patch.

Paul

I think this would be the best option, as you can simply use the existing code. Although you probably need to make some adjustments here and there, for which you could write a plugin/patch.

Eloy

There is a lot of magic in Rails that I'm trying to get my head
around. Specifically, I get this error with Ruby -r24788 (today's
snapshot) and Rails (fails both in 2.3.4 and edge).

I would like to work out if this is a 1.9.2 incompatibility with Rails
or a bug in Ruby (most likely the latter):

  foo@studio:~/work/bar$ rake db:migrate --trace

  (snip)

  ** Execute db:migrate
  rake aborted!
  undefined method `singleton_method_added' for ActiveRecord::Migration:Class
  /home/foo/backup/work/bar/vendor/rails/activerecord/lib/active_record/migration.rb:297:in `singletonclass'
  /home/foo/backup/work/bar/vendor/rails/activerecord/lib/active_record/migration.rb:265:in `<class:Migration>'
  /home/foo/backup/work/bar/vendor/rails/activerecord/lib/active_record/migration.rb:261:in `<module:ActiveRecord>'
  /home/foo/backup/work/bar/vendor/rails/activerecord/lib/active_record/migration.rb:3:in `<top (required)>'
  /home/foo/backup/work/bar/vendor/rails/railties/lib/tasks/databases.rake:135:in `block (2 levels) in <top (required)>'

  (snip)

It seems like its trying to call singleton_method_added before it
actually is defined. I wanted to isolate a test case for the ruby
parser - where is this called from, or how is the singleton instance
callback set up?

This is caused by the call (cattr_accessor):

  ActiveRecord::Migration.verbose = ...

Any tips or documentation pointers would help.

Thanks in advance.