Good point David, this can be very dangerous if always enabled due to
form injection. But when intentionally enabled, this has the potential
to greatly simplify multi-model forms - which I love!

Out of curiosity, have you tried making a multi-model form with this?
I can if you want. There are a lot of complexities involved,
specifically with regards to when the associated models are saved and
what happens when validation fails.

Ryan


On Jul 17, 4:41 pm, David Dollar <[EMAIL PROTECTED]> wrote:
> > On Jul 16, 7:57 pm, Pratik <[EMAIL PROTECTED]> wrote:
> >> Has anyone any strong opinions against this ? I'm very interested in
> >> hearing more thoughts on this and/or if you have any suggestions to
> >> improvise David's approaches.
>
> >> Thanks,
> >> Pratik
>
> > Is the :accessible specifier necessary?  In other words, are we afraid
> > something might break if ActiveRecord::Base#new and #create natively
> > understood nested hashes as well as the flat hashes that it can accept
> > today?
>
> > Jeff
>
> The main concern that I have seen presented is that form injection
> could cause data to be created/updated around your database
> that you did not intend should the attacker carefully craft a form for
> submission.
>
> David
>
> >> On Jul 14, 6:38 pm, David Dollar <[EMAIL PROTECTED]> wrote:
>
> >>> Recently the following patch
>
> >>>http://github.com/rails/rails/commit/e0750d6a5c7f621e4ca12205137c0b13
> >>> ...
>
> >>> 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/14a16844bbb3ba9edb14269ce2d0b6
> >>> ...
>
> >>> 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/61
> >>> ...
>
> >>> 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
>
>  smime.p7s
> 2KDownload
--~--~---------~--~----~------------~-------~--~----~
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