This repository has been archived by the owner on Dec 12, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
82 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |