This project is archived and is in readonly mode.
Allow Hash to be passed into AssociationProxy setters and AssociationCollections
-
David Dollar
Refactored the patch to add ActiveRecord::Base#attr_creatable to permit this functionality
-
David Dollar
Also found at http://github.com/ddollar/rails/...
-
Pascal Ehlert
- Tag changed from activerecord, patch to activerecord, patch, tested
Checked it out, tests are passing. Looks good, would like to see this feature soon.
-
Pratik
- Assigned user set to Pratik
-
David Dollar
Reworked as has_many :foo, :accessible => true
-
Repository
(from [e0750d6a5c7f621e4ca12205137c0b135cab444a]) Add :accessible option to Associations for allowing mass assignments using hash. [#474 state:resolved]
Allows nested Hashes (i.e. from nested forms) to hydrate the appropriate
ActiveRecord models.
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' }
Signed-off-by: Pratik Naik
-
Pratik
- State changed from new to resolved
-
Pascal Ehlert
Okay, I'm a bit in a hurry now and just want to make a quick note before I forgot. I will go into more detail about this later.
If we now also allow attributes for has_many associations, wouldn't it make sense to do it in the way that AttributeFu does it, in order to make it possible to create/update both, existing and new records?
I actually see few cases were only creation is useful.
-
David Dollar
I'm not sure what you mean. Updating currently works with this change.
class Author < ActiveRecord::Base has_many :posts, :accessible => true end class Post < ActiveRecord::Base belongs_to :author, :accessible => true end > Post.create({:title => 'Foo', :author => { :name => 'David' }}) => #<Post id: 1, author_id: 1, title: "Foo", created_at: "2008-07-14 12:42:39", updated_at: "2008-07-14 12:42:39"> > p = Post.find(1) => #<Post id: 1, author_id: 1, title: "Foo", created_at: "2008-07-14 12:42:39", updated_at: "2008-07-14 12:42:39"> > p.author = { :name => 'Joe' } => {:name=>"Joe"}> p.save => true > p => #<Post id: 1, author_id: 2, title: "Foo", created_at: "2008-07-14 12:42:39", updated_at: "2008-07-14 12:43:11"> > p.author => #<Author id: 2, name: "Joe", created_at: "2008-07-14 12:43:11", updated_at: "2008-07-14 12:43:11"> > a = Author.find(2) => #<Author id: 2, name: "Joe", created_at: "2008-07-14 12:43:11", updated_at: "2008-07-14 12:43:11"> > a.posts => [#<Post id: 1, author_id: 2, title: "Foo", created_at: "2008-07-14 12:42:39", updated_at: "2008-07-14 12:43:11">] > a.posts << { :title => 'Another Post' } => [#<Post id: 1, author_id: 2, title: "Foo", created_at: "2008-07-14 12:42:39", updated_at: "2008-07-14 12:43:11">, #<Post id: 2, author_id: 2, title: "Another Post", created_at: "2008-07-14 12:45:49", updated_at: "2008-07-14 12:45:49">] > a.posts.last => #<Post id: 2, author_id: 2, title: "Another Post", created_at: "2008-07-14 12:45:49", updated_at: "2008-07-14 12:45:49"> -
Pascal Ehlert
Sure, it works for has_one and belongs_to, but not so well for has_many.
It will only create a new record and delete the old one which I don't think is a good behavior.
-
David Dollar
I think I see what you mean. Let me see what I can come up with.
--
David Dollar
On Jul 14, 2008, at 9:02 AM, Lighthouse
wrote:
-
David Dollar
Adds the ability to update existing entries on :accessible => true associations
# 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 15:40:30", updated_at: "2008-07-14 15:40:30">, #<Post id: 20, author_id: 14, title: "New Post", created_at: "2008-07-14 15:43:18", updated_at: "2008-07-14 15:43:18">] -
James
This approach seems fairly limited.
We couldn't have a form, for example, that would be able to update, and create new child models at once.
My plugin, attribute_fu (mentioned earlier), does the same thing, but supports all the cases where there are both new and saved objects in the hash of hashes. It is a fully transparent solution for creating multi-model forms, including form helpers.
Is there any chance of extending this syntax to support those situations, or sucking attribute_fu down in to core?
If you're unfamiliar with the plugin, checkout this screencast
-
David Dollar
- No changes were found…
-
David Dollar
The second patch mentioned here adds all of the features you are looking for. To mix both creating and updating simply specify some elements of the hash with :id keys and others without.
-
Repository
(from [9994f0d90248db7d7eae36f0b597a15e8a427612]) Revert "Add :accessible option to Associations for allowing mass assignments using hash. [#474 Allow Hash to be passed into AssociationProxy setters and AssociationCollections state:resolved]"
This reverts commit e0750d6a5c7f621e4ca12205137c0b135cab444a.
Conflicts:
activerecord/CHANGELOG activerecord/lib/active_record/associations.rb activerecord/lib/active_record/associations/association_collection.rb -
Brian Mitchell
Any word on what might replace this functionality or is it gone for the time being?
-
Sean Kirby
Continued in #1031 handle parameterized associations and here: http://groups.google.com/group/r...
-
Andrew Vit
Why is this ticket marked "resolved" if the feature was pulled?
