Recently the following patch

http://github.com/rails/rails/commit/e0750d6a5c7f621e4ca12205137c0b135cab444a

was committed to rails trunk. This patch allows for associations to be
flagged as :accessible => true and then hydrated from nested hashes
(i.e. nested forms)

class Post < ActiveRecord::Base
  belongs_to :author,   :accessible => true
  has_many   :comments, :accessible => true
end

post = Post.create({
  :title    => 'Accessible Attributes',
  :author   => { :name => 'David Dollar' },
  :comments => [
    { :body => 'First Post!' },
    { :body => 'Nested Hashes are great!' }
  ]
})

post.comments << { :body => 'Another Comment' }

I have done some work on another patch to allow this same mechanism to
be used for updating existing rows using nested hashes. This completes
the work as far as dynamically generating forms and being able to
simply and intuitively push them back into the database.

http://github.com/ddollar/rails/commit/14a16844bbb3ba9edb14269ce2d0b61c9a43637e

This allows for the following:

# create from a basic hash
> p = Post.create(:title => 'Test Post', :author => { :name => 'David' })
=> #<Post id: 8, author_id: 8, title: "Test Post", created_at:
"2008-07-14 15:22:53", updated_at: "2008-07-14 15:22:53">

# update a singular reference
> p.author = { :name => 'Joe' }
=> {:name=>"Joe"}

# it 'updates' the row in sql, notice the id is still the same
> p.author
=> #<Author id: 8, name: "Joe", created_at: "2008-07-14 15:22:53",
updated_at: "2008-07-14 15:23:03">


# create an author with posts from a hash
>  a = Author.create(:name => 'David', :posts => [ { :title => 'Post 1' }, { 
> :title => 'Post 2' } ])
=> #<Author id: 14, name: "David", created_at: "2008-07-14 15:38:18",
updated_at: "2008-07-14 15:38:18">

# show the posts
> a.posts
=> [#<Post id: 17, author_id: 14, title: "Post 1", created_at:
"2008-07-14 15:38:18", updated_at: "2008-07-14 15:38:18">, #<Post id:
18, author_id: 14, title: "Post 2", created_at: "2008-07-14 15:38:18",
updated_at: "2008-07-14 15:38:18">]

# use << to update existing entries (as well as add new ones,
demonstrated later)
> a.posts << { :id => 17, :title => 'Post 1 Updated' }
=> [#<Post id: 17, author_id: 14, title: "Post 1 Updated", created_at:
"2008-07-14 15:38:18", updated_at: "2008-07-14 15:38:53">, #<Post id:
18, author_id: 14, title: "Post 2", created_at: "2008-07-14 15:38:18",
updated_at: "2008-07-14 15:38:18">]

# show posts to verify the update
> a.posts
=> [#<Post id: 17, author_id: 14, title: "Post 1 Updated", created_at:
"2008-07-14 15:38:18", updated_at: "2008-07-14 15:38:53">, #<Post id:
18, author_id: 14, title: "Post 2", created_at: "2008-07-14 15:38:18",
updated_at: "2008-07-14 15:38:18">]

# can't update posts that don't belong to the author
> a.posts << { :id => 1, :title => 'Not Allowed' }
ActiveRecord::RecordNotFound: Couldn't find Post with ID=1 AND
("posts".author_id = 14)
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/base.rb:1393:in `find_one'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/base.rb:1376:in `find_from_ids'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/base.rb:537:in `find'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/associations/association_collection.rb:
47:in `find'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/associations/association_collection.rb:
103:in `<<'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/associations/association_collection.rb:
99:in `each'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/associations/association_collection.rb:
99:in `<<'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/connection_adapters/abstract/
database_statements.rb:66:in `transaction'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/transactions.rb:79:in `transaction'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/transactions.rb:98:in `transaction'
        from /Users/ddollar/Code/EdgeRailsApp/vendor/rails/
activerecord/lib/active_record/associations/association_collection.rb:
98:in `<<'
        from (irb):12

# use = to outright replace all posts
> a.posts = [ { :title => 'Replace Posts' } ]
=> [#<Post id: 19, author_id: 14, title: "Replace Posts", created_at:
"2008-07-14 15:40:30", updated_at: "2008-07-14 15:40:30">]

# can even 'replace' using existing posts, the post attributes will be
updated
> a.posts = [ { :id => 19, :title => 'Can Replace This Way Too' } ]
=> [#<Post id: 19, author_id: 14, title: "Can Replace This Way Too",
created_at: "2008-07-14 15:40:30", updated_at: "2008-07-14 15:40:49">]

# use << also for adding brand new items
> a.posts << { :title => 'New Post' }
=> [#<Post id: 19, author_id: 14, title: "Replace Posts", created_at:
"2008-07-14

The patch can be found at

http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/619-allow-accessible-true-associations-to-update-records

I was asked to submit this patch to the mailing list and solicit any
comments. Does anyone see any obvious holes or ways this functionality
should change?


Thanks,
David Dollar
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To post to this group, send email to rubyonrails-core@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-core?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to