Browse files

importing untested concept code

  • Loading branch information...
1 parent ee80059 commit e1a484f31c7f8d50ee66ccdb9f2b6ed6b3add0e1 @cainlevy committed Dec 11, 2008
Showing with 82 additions and 7 deletions.
  1. +14 −3 README
  2. +67 −0 lib/nested_assignment.rb
  3. +1 −4 test/nested_assignment_test.rb
View
17 README
@@ -1,9 +1,8 @@
-NestedAssignment
-================
+= NestedAssignment
An attempt at solving the model (and controller) side of nested forms. Based on thoughts pulled from http://groups.google.com/group/rubyonrails-core/browse_thread/thread/4049b4b313fa8be2, http://groups.google.com/group/rubyonrails-core/browse_thread/thread/3c61e00916c365e5/f0a19fc01d0246fc, and work on ActiveScaffold.
-Goals:
+== Goals:
# Assigning attributes should remain in-memory. Nothing should be permanent before #save. This means avoiding some of ActiveRecord's association assignment logic such as AssociationCollection#replace.
# Deep and thorough validation of all new and changed associated records. In order for all possible errors to be available at once, no single invalid record may halt the process.
@@ -16,4 +15,16 @@ and of course:
# Skinny controllers. There's no footprint in the controller, actually.
+== Paradigm Params (cf http://gist.github.com/10793)
+
+ {
+ :task_params =>
+ {
+ '1' => { :id => '3', :name => "Foo" },
+ '2' => { :id => '5', :name => "Bar", :_delete => true}
+ '3' => { :name => "Baz" }
+ }
+ }
+
+
Copyright (c) 2008 Lance Ivy, released under the MIT license
View
67 lib/nested_assignment.rb
@@ -1 +1,68 @@
# NestedAssignment
+module NestedAssignment
+ def self.included(base)
+ base.class_eval do extend ClassMethods end
+ end
+
+ module ClassMethods
+ # Parallels attr_accessible. Could easily trigger from :accessible => true instead.
+ def accessible_associations(*associations)
+ associations.each do |name|
+
+ define_method("#{name}_params=") do |hash|
+ assoc = self.send(name)
+ hash.values.each do |row|
+ record = row[:id].blank? ? assoc.build : assoc.select{|r| r.id == row[:id].to_i}
+ if row[:_delete]
+ record._delete = true
+ else
+ record.attributes = row
+ end
+ end
+ end
+
+ end
+ end
+
+ protected
+
+ def self.association_names
+ @association_names ||= reflect_on_all_associations.map(&:name)
+ end
+ end
+
+ # marks the record to be deleted in the next save
+ attr_accessor :_delete
+
+ # deep validation of any changed (or new) records.
+ # makes sure that any single invalid record will not halt the
+ # validation process, so that all errors will be available
+ # afterwards.
+ def valid?
+ [changed_associated.all?(&:valid?), super].all?
+ end
+
+ # deep saving of any new, changed, or deleted records.
+ def save
+ self.class.transaction do
+ super
+ changed_associated.each(&:save)
+ deletable_associated.each(&:destroy)
+ end
+ end
+
+ protected
+
+ def deletable_associated
+ instantiated_associated.select(&:_delete)
+ end
+
+ def changed_associated
+ instantiated_associated.select(&:changed?
+ end
+
+ def instantiated_associated
+ self.class.associations_names.collect{ |name| [self.send(name).target] }.flatten
+ end
+
+end
View
5 test/nested_assignment_test.rb
@@ -1,8 +1,5 @@
require 'test_helper'
class NestedAssignmentTest < ActiveSupport::TestCase
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+
end

0 comments on commit e1a484f

Please sign in to comment.