Skip to content
This repository has been archived by the owner on Dec 12, 2018. It is now read-only.

Commit

Permalink
importing untested concept code
Browse files Browse the repository at this point in the history
  • Loading branch information
cainlevy committed Dec 11, 2008
1 parent ee80059 commit e1a484f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 7 deletions.
17 changes: 14 additions & 3 deletions README
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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
67 changes: 67 additions & 0 deletions lib/nested_assignment.rb
Original file line number Diff line number Diff line change
@@ -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
5 changes: 1 addition & 4 deletions test/nested_assignment_test.rb
Original file line number Diff line number Diff line change
@@ -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.