On Jul 18, 2008, at 10:52 AM, Ryan Bates wrote:

>
> 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.

Yep, exactly.  I talked with David Dollar on IRC about this.  I've  
done this in a way that is similar to your recipe in ARR, but I create/ 
update the associated models in a before_validation callback, rather  
than in the setter.  That keeps everything in one transaction and  
makes it a little easier to handle validation issues.  I did like your  
approach of splitting the setters into two pieces for create and  
update.  The one thing that keeps bugging me though is doing deletes -  
I've still yet to figure out a really nice way to handle that.

--josh


>
>
> 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
> >

--
Josh Susser
http://blog.hasmanythrough.com



--~--~---------~--~----~------------~-------~--~----~
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