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

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to