activeshepherd 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Guardfile +16 -0
- data/LICENSE.txt +22 -0
- data/README.md +138 -0
- data/Rakefile +24 -0
- data/activeshepherd.gemspec +34 -0
- data/lib/active_shepherd.rb +24 -0
- data/lib/active_shepherd/active_record_shim.rb +15 -0
- data/lib/active_shepherd/aggregate.rb +69 -0
- data/lib/active_shepherd/aggregate_root.rb +152 -0
- data/lib/active_shepherd/changes_validator.rb +11 -0
- data/lib/active_shepherd/class_validator.rb +11 -0
- data/lib/active_shepherd/deep_reverse_changes.rb +22 -0
- data/lib/active_shepherd/method.rb +81 -0
- data/lib/active_shepherd/methods/apply_changes.rb +53 -0
- data/lib/active_shepherd/methods/apply_state.rb +58 -0
- data/lib/active_shepherd/methods/query_changes.rb +53 -0
- data/lib/active_shepherd/methods/query_state.rb +38 -0
- data/lib/active_shepherd/traversal.rb +34 -0
- data/lib/active_shepherd/version.rb +3 -0
- data/lib/activeshepherd.rb +1 -0
- data/tags +123 -0
- data/test/integration/.gitkeep +0 -0
- data/test/integration/project_todo_scenario_test.rb +334 -0
- data/test/setup_test_models.rb +115 -0
- data/test/test_helper.rb +21 -0
- data/test/unit/.gitkeep +0 -0
- data/test/unit/aggregate_test.rb +4 -0
- data/test/unit/apply_changes_test.rb +17 -0
- data/test/unit/changes_validator_test.rb +19 -0
- data/test/unit/class_validator_test.rb +39 -0
- metadata +257 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
class ActiveShepherd::DeepReverseChanges < Struct.new(:changes)
|
2
|
+
def reverse
|
3
|
+
changer = ->(h) {
|
4
|
+
unless h.is_a?(Hash)
|
5
|
+
binding.pry
|
6
|
+
end
|
7
|
+
h.each_with_object({}) do |(k,v), new_hash|
|
8
|
+
if v.is_a?(Array) && v.size == 2
|
9
|
+
new_hash[k] = [v.last, v.first]
|
10
|
+
elsif v.is_a?(Hash)
|
11
|
+
new_hash[k] = changer.call(v)
|
12
|
+
elsif :_create == k.to_sym
|
13
|
+
new_hash[:_destroy] = v
|
14
|
+
elsif :_destroy == k.to_sym
|
15
|
+
new_hash[:_create] = v
|
16
|
+
end
|
17
|
+
end
|
18
|
+
}
|
19
|
+
|
20
|
+
changer.call(changes)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ActiveShepherd
|
2
|
+
class Method
|
3
|
+
attr_reader :associations, :attributes
|
4
|
+
|
5
|
+
def self.inherited(base)
|
6
|
+
# If you're looking for magic, you've come to the right place
|
7
|
+
return unless base.name.match /Methods::/
|
8
|
+
apply_or_query, state_or_changes = base.name.demodulize.underscore.split('_', 2)
|
9
|
+
method_name = "#{apply_or_query}_#{state_or_changes}"
|
10
|
+
action_proc = ->(*args) { new(*args).send(method_name) }
|
11
|
+
base.singleton_class.send :define_method, method_name, &action_proc
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :aggregate
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
@aggregate = args.shift
|
18
|
+
@associations = {}
|
19
|
+
@attributes = {}
|
20
|
+
|
21
|
+
setup *args
|
22
|
+
end
|
23
|
+
|
24
|
+
def recurse(model, foreign_key)
|
25
|
+
Aggregate.new model, foreign_key
|
26
|
+
end
|
27
|
+
|
28
|
+
def traverse!
|
29
|
+
Traversal.new(
|
30
|
+
self,
|
31
|
+
attributes: attributes,
|
32
|
+
associations: associations,
|
33
|
+
).traverse
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class QueryMethod < ActiveShepherd::Method
|
38
|
+
attr_reader :query
|
39
|
+
|
40
|
+
def initialize(*args)
|
41
|
+
super
|
42
|
+
@query = {}
|
43
|
+
end
|
44
|
+
|
45
|
+
def setup
|
46
|
+
@associations = aggregate.traversable_associations
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class ApplyMethod < ActiveShepherd::Method
|
51
|
+
attr_reader :meta_action
|
52
|
+
|
53
|
+
def create?
|
54
|
+
meta_action == :_create
|
55
|
+
end
|
56
|
+
|
57
|
+
def destroy?
|
58
|
+
meta_action == :_destroy
|
59
|
+
end
|
60
|
+
|
61
|
+
def setup(hash)
|
62
|
+
hash.each do |key, value|
|
63
|
+
traversable_association = aggregate.traversable_associations[key]
|
64
|
+
if traversable_association.present?
|
65
|
+
associations[key] = [traversable_association, value]
|
66
|
+
elsif aggregate.untraversable_association_names.include? key
|
67
|
+
elsif [:_create, :_destroy].include? key
|
68
|
+
@meta_action = key
|
69
|
+
elsif aggregate.raw_attributes.keys.include? key.to_s
|
70
|
+
attributes[key] = value
|
71
|
+
else
|
72
|
+
raise ActiveShepherd::AggregateMismatchError, "Attribute `#{key}' "\
|
73
|
+
"invalid for `#{aggregate.model.class.name}'"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Set up namespace for the method classes
|
80
|
+
Methods = Module.new
|
81
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class ActiveShepherd::Methods::ApplyChanges < ActiveShepherd::ApplyMethod
|
2
|
+
def apply_changes
|
3
|
+
aggregate.model.mark_for_destruction if destroy?
|
4
|
+
traverse!
|
5
|
+
end
|
6
|
+
|
7
|
+
def handle_attribute(attribute_name, before_and_after)
|
8
|
+
before, after = before_and_after
|
9
|
+
current_value = aggregate.model.send(attribute_name)
|
10
|
+
|
11
|
+
before = aggregate.deserialize_value(attribute_name, before)
|
12
|
+
after = aggregate.deserialize_value(attribute_name, after)
|
13
|
+
|
14
|
+
unless current_value == before
|
15
|
+
raise ::ActiveShepherd::AggregateRoot::BadChangeError, "Expecting "\
|
16
|
+
"`#{attribute_name} to be `#{before.inspect}', not "\
|
17
|
+
"`#{current_value.inspect}'"
|
18
|
+
end
|
19
|
+
|
20
|
+
aggregate.model.send "#{attribute_name}=", after
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_has_many_association(reflection, collection_changes)
|
24
|
+
apply_changes_to_has_many_association reflection, collection_changes
|
25
|
+
end
|
26
|
+
|
27
|
+
def handle_has_one_association(reflection, changes)
|
28
|
+
associated_model = aggregate.model.public_send reflection.name
|
29
|
+
self.class.apply_changes recurse(associated_model, reflection.foreign_key),
|
30
|
+
changes
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def apply_changes_to_has_many_association(reflection, collection_changes)
|
36
|
+
association = aggregate.model.send reflection.name
|
37
|
+
|
38
|
+
collection_changes.each do |index, changes|
|
39
|
+
# FIXME
|
40
|
+
association.build until association.size >= (index + 1)
|
41
|
+
# /FIXME
|
42
|
+
|
43
|
+
associated_model = association[index]
|
44
|
+
if associated_model.nil?
|
45
|
+
raise ::ActiveShepherd::AggregateRoot::BadChangeError,
|
46
|
+
"Can't find record ##{index}"
|
47
|
+
end
|
48
|
+
self.class.apply_changes recurse(associated_model, reflection.foreign_key),
|
49
|
+
changes
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class ActiveShepherd::Methods::ApplyState < ActiveShepherd::ApplyMethod
|
2
|
+
def apply_state
|
3
|
+
mark_all_associated_objects_for_destruction
|
4
|
+
apply_default_state_to_root_model
|
5
|
+
traverse!
|
6
|
+
end
|
7
|
+
|
8
|
+
def handle_attribute(attribute_name, raw_value)
|
9
|
+
value = aggregate.deserialize_value attribute_name, raw_value
|
10
|
+
aggregate.model.send "#{attribute_name}=", value
|
11
|
+
end
|
12
|
+
|
13
|
+
def handle_has_many_association(reflection, collection_state)
|
14
|
+
association = aggregate.model.send reflection.name
|
15
|
+
collection_state.each do |state|
|
16
|
+
associated_model = association.build
|
17
|
+
self.class.apply_state recurse(associated_model, reflection.foreign_key),
|
18
|
+
state
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def handle_has_one_association(reflection, state)
|
23
|
+
associated_model = aggregate.model.send "build_#{reflection.name}"
|
24
|
+
self.class.apply_state recurse(associated_model, reflection.foreign_key),
|
25
|
+
state
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def apply_default_state_to_root_model
|
31
|
+
default_attributes = aggregate.default_attributes
|
32
|
+
ignored_attribute_names = attributes.keys.map(&:to_s) + aggregate.excluded_attributes
|
33
|
+
|
34
|
+
(default_attributes.keys - ignored_attribute_names).each do |attribute_name|
|
35
|
+
current_value = aggregate.model.attributes[attribute_name]
|
36
|
+
default_value = default_attributes[attribute_name]
|
37
|
+
|
38
|
+
unless aggregate.deserialize_value(attribute_name, default_value) == default_value
|
39
|
+
raise 'Have not handled this use case yet; serialized attributes with a default value'
|
40
|
+
end
|
41
|
+
|
42
|
+
next if default_value == current_value
|
43
|
+
|
44
|
+
aggregate.model.send("#{attribute_name}=", default_value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def mark_all_associated_objects_for_destruction
|
49
|
+
aggregate.traversable_associations.each do |name, association_reflection|
|
50
|
+
if association_reflection.macro == :has_many
|
51
|
+
aggregate.model.send(name).each { |record| record.mark_for_destruction }
|
52
|
+
elsif association_reflection.macro == :has_one
|
53
|
+
aggregate.model.send(name).try(&:mark_for_destruction)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class ActiveShepherd::Methods::QueryChanges < ActiveShepherd::QueryMethod
|
2
|
+
def query_changes
|
3
|
+
traverse!
|
4
|
+
set_meta_action
|
5
|
+
query
|
6
|
+
end
|
7
|
+
|
8
|
+
def handle_attribute(attribute_name, before, after)
|
9
|
+
query[attribute_name] = [before, after]
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle_has_many_association(reflection)
|
13
|
+
association = aggregate.model.send reflection.name
|
14
|
+
|
15
|
+
collection_changes = association.each.with_object({}).with_index do |(associated_model, h), index|
|
16
|
+
changes = self.class.query_changes recurse(associated_model, reflection.foreign_key)
|
17
|
+
h[index] = changes unless changes.blank?
|
18
|
+
end
|
19
|
+
|
20
|
+
unless collection_changes.blank?
|
21
|
+
query[reflection.name] = collection_changes
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_has_one_association(reflection)
|
26
|
+
associated_model = aggregate.model.send reflection.name
|
27
|
+
return unless associated_model.present?
|
28
|
+
|
29
|
+
changes = self.class.query_changes recurse(associated_model, reflection.foreign_key)
|
30
|
+
query[reflection.name] = changes unless changes.blank?
|
31
|
+
end
|
32
|
+
|
33
|
+
def setup
|
34
|
+
super
|
35
|
+
@attributes = aggregate.model.changes.each_with_object({}) do |(name,changes),h|
|
36
|
+
next if aggregate.excluded_attributes.include? name.to_s
|
37
|
+
h[name.to_sym] = changes.map do |raw_value|
|
38
|
+
aggregate.serialize_value name, raw_value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def set_meta_action
|
46
|
+
if not aggregate.model.persisted?
|
47
|
+
query[:_create] = '1'
|
48
|
+
elsif aggregate.model.marked_for_destruction?
|
49
|
+
query[:_destroy] = '1'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class ActiveShepherd::Methods::QueryState < ActiveShepherd::QueryMethod
|
2
|
+
def query_state
|
3
|
+
traverse!
|
4
|
+
query
|
5
|
+
end
|
6
|
+
|
7
|
+
def handle_attribute(name, value)
|
8
|
+
query[name] = value
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle_has_many_association(reflection)
|
12
|
+
association = aggregate.model.send reflection.name
|
13
|
+
collection_state = association.map do |associated_model|
|
14
|
+
self.class.query_state recurse(associated_model, reflection.foreign_key)
|
15
|
+
end
|
16
|
+
query[reflection.name] = collection_state unless collection_state.blank?
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle_has_one_association(reflection)
|
20
|
+
associated_model = aggregate.model.send reflection.name
|
21
|
+
if associated_model
|
22
|
+
state = self.class.query_state recurse(associated_model, reflection.foreign_key)
|
23
|
+
query[reflection.name] = state unless state.blank?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup
|
28
|
+
super
|
29
|
+
@attributes = aggregate.raw_attributes.each_with_object({}) do |(name,raw),h|
|
30
|
+
next if aggregate.excluded_attributes.include? name
|
31
|
+
value = aggregate.serialize_value name, raw
|
32
|
+
unless value == aggregate.default_attributes[name]
|
33
|
+
h[name.to_sym] = value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class ActiveShepherd::Traversal
|
2
|
+
attr_reader :attributes, :associations, :visitor
|
3
|
+
|
4
|
+
def initialize(visitor, params = {})
|
5
|
+
@associations = params[:associations]
|
6
|
+
@attributes = params[:attributes]
|
7
|
+
@visitor = visitor
|
8
|
+
end
|
9
|
+
|
10
|
+
def traverse
|
11
|
+
attributes.each do |attribute_name, object|
|
12
|
+
visit :handle_attribute, attribute_name, object
|
13
|
+
end
|
14
|
+
|
15
|
+
associations.each do |name, (reflection, object)|
|
16
|
+
if reflection.macro == :has_many
|
17
|
+
visit :handle_has_many_association, reflection, object
|
18
|
+
elsif reflection.macro == :has_one
|
19
|
+
visit :handle_has_one_association, reflection, object
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def visit(method_name, arg1, arg2)
|
25
|
+
if visitor.respond_to? method_name
|
26
|
+
if visitor.method(method_name).arity == 2
|
27
|
+
visitor.public_send method_name, arg1, arg2
|
28
|
+
else
|
29
|
+
visitor.public_send method_name, arg1, *Array.wrap(arg2)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_shepherd'
|
data/tags
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
2
|
+
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
3
|
+
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
|
4
|
+
!_TAG_PROGRAM_NAME Exuberant Ctags //
|
5
|
+
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
|
6
|
+
!_TAG_PROGRAM_VERSION 5.8 //
|
7
|
+
ActiveShepherd lib/active_shepherd.rb /^module ActiveShepherd ; end$/;" m
|
8
|
+
ActiveShepherd lib/active_shepherd.rb /^module ActiveShepherd$/;" m
|
9
|
+
ActiveShepherd lib/active_shepherd/active_record_shim.rb /^module ActiveShepherd$/;" m
|
10
|
+
ActiveShepherd lib/active_shepherd/aggregate.rb /^class ActiveShepherd::Aggregate$/;" c
|
11
|
+
ActiveShepherd lib/active_shepherd/aggregate_root.rb /^module ActiveShepherd::AggregateRoot$/;" m
|
12
|
+
ActiveShepherd lib/active_shepherd/apply_changes.rb /^class ActiveShepherd::ApplyChanges < ActiveShepherd::StateMethod$/;" c
|
13
|
+
ActiveShepherd lib/active_shepherd/apply_state.rb /^class ActiveShepherd::ApplyState < ActiveShepherd::StateMethod$/;" c
|
14
|
+
ActiveShepherd lib/active_shepherd/deep_reverse_changes.rb /^class ActiveShepherd::DeepReverseChanges < Struct.new(:changes)$/;" c
|
15
|
+
ActiveShepherd lib/active_shepherd/query_changes.rb /^class ActiveShepherd::QueryChanges < ActiveShepherd::StateMethod$/;" c
|
16
|
+
ActiveShepherd lib/active_shepherd/query_state.rb /^class ActiveShepherd::QueryState < ActiveShepherd::StateMethod$/;" c
|
17
|
+
ActiveShepherd lib/active_shepherd/state_method.rb /^class ActiveShepherd::StateMethod$/;" c
|
18
|
+
ActiveShepherd lib/active_shepherd/version.rb /^module ActiveShepherd$/;" m
|
19
|
+
AggregateTest test/unit/aggregate_test.rb /^class AggregateTest < MiniTest::Unit::TestCase$/;" c
|
20
|
+
ClassMethods lib/active_shepherd/aggregate_root.rb /^ module ClassMethods$/;" m class:ActiveShepherd
|
21
|
+
Comment test/setup_test_models.rb /^class Comment < ActiveRecord::Base$/;" c
|
22
|
+
IntegrationTest test/integration/project_todo_scenario_test.rb /^class IntegrationTest < MiniTest::Unit::TestCase$/;" c
|
23
|
+
Project test/setup_test_models.rb /^class Project < ActiveRecord::Base$/;" c
|
24
|
+
Project test/setup_test_models.rb /^class Project::Comment < Comment$/;" c
|
25
|
+
Project test/setup_test_models.rb /^class Project::Detail < ActiveRecord::Base$/;" c
|
26
|
+
Project test/setup_test_models.rb /^class Project::Todo < ActiveRecord::Base$/;" c
|
27
|
+
Project test/setup_test_models.rb /^class Project::TodoAssignment < ActiveRecord::Base$/;" c
|
28
|
+
Project test/setup_test_models.rb /^class Project::TodoList < ActiveRecord::Base$/;" c
|
29
|
+
able_to_act_as_aggregate_root? lib/active_shepherd/active_record_shim.rb /^ def able_to_act_as_aggregate_root?$/;" f class:ActiveShepherd.enable
|
30
|
+
act_as_aggregate_root! lib/active_shepherd/active_record_shim.rb /^ def act_as_aggregate_root!$/;" f class:ActiveShepherd.enable
|
31
|
+
add_changes_on_association lib/active_shepherd/query_changes.rb /^ def add_changes_on_association(association_reflection)$/;" f class:ActiveShepherd
|
32
|
+
add_changes_on_associations lib/active_shepherd/query_changes.rb /^ def add_changes_on_associations$/;" f class:ActiveShepherd
|
33
|
+
add_changes_on_has_many_association lib/active_shepherd/query_changes.rb /^ def add_changes_on_has_many_association(name, foreign_key)$/;" f class:ActiveShepherd
|
34
|
+
add_changes_on_has_one_association lib/active_shepherd/query_changes.rb /^ def add_changes_on_has_one_association(name, foreign_key)$/;" f class:ActiveShepherd
|
35
|
+
add_changes_on_root_model lib/active_shepherd/query_changes.rb /^ def add_changes_on_root_model$/;" f class:ActiveShepherd
|
36
|
+
add_state_from_association lib/active_shepherd/query_state.rb /^ def add_state_from_association(name, association_reflection)$/;" f class:ActiveShepherd
|
37
|
+
add_state_from_root_model lib/active_shepherd/query_state.rb /^ def add_state_from_root_model$/;" f class:ActiveShepherd
|
38
|
+
aggregate_changes lib/active_shepherd/aggregate_root.rb /^ def aggregate_changes$/;" f class:ActiveShepherd
|
39
|
+
aggregate_changes= lib/active_shepherd/aggregate_root.rb /^ def aggregate_changes=(changes)$/;" f class:ActiveShepherd
|
40
|
+
aggregate_state lib/active_shepherd/aggregate_root.rb /^ def aggregate_state$/;" f class:ActiveShepherd
|
41
|
+
aggregate_state= lib/active_shepherd/aggregate_root.rb /^ def aggregate_state=(blob)$/;" f class:ActiveShepherd
|
42
|
+
aggro lib/active_shepherd/aggregate_root.rb /^ def aggro$/;" f class:ActiveShepherd
|
43
|
+
apply_changes lib/active_shepherd/apply_changes.rb /^ def apply_changes$/;" f class:ActiveShepherd
|
44
|
+
apply_changes_to_associated_model lib/active_shepherd/apply_changes.rb /^ def apply_changes_to_associated_model(model, foreign_key, changes)$/;" f class:ActiveShepherd
|
45
|
+
apply_changes_to_association lib/active_shepherd/apply_changes.rb /^ def apply_changes_to_association(association_reflection, changes_or_changes_set)$/;" f class:ActiveShepherd
|
46
|
+
apply_changes_to_associations lib/active_shepherd/apply_changes.rb /^ def apply_changes_to_associations$/;" f class:ActiveShepherd
|
47
|
+
apply_changes_to_attribute lib/active_shepherd/apply_changes.rb /^ def apply_changes_to_attribute(attribute_name, before, after)$/;" f class:ActiveShepherd
|
48
|
+
apply_changes_to_has_many_association lib/active_shepherd/apply_changes.rb /^ def apply_changes_to_has_many_association(association_reflection, foreign_key, changes_set)$/;" f class:ActiveShepherd
|
49
|
+
apply_changes_to_has_one_association lib/active_shepherd/apply_changes.rb /^ def apply_changes_to_has_one_association(association_reflection, foreign_key, changes)$/;" f class:ActiveShepherd
|
50
|
+
apply_changes_to_root_model lib/active_shepherd/apply_changes.rb /^ def apply_changes_to_root_model$/;" f class:ActiveShepherd
|
51
|
+
apply_default_state_to_root_model lib/active_shepherd/apply_state.rb /^ def apply_default_state_to_root_model$/;" f class:ActiveShepherd
|
52
|
+
apply_state lib/active_shepherd/apply_state.rb /^ def apply_state$/;" f class:ActiveShepherd
|
53
|
+
apply_state_to_associated_model lib/active_shepherd/apply_state.rb /^ def apply_state_to_associated_model(associated_model, foreign_key, state)$/;" f class:ActiveShepherd
|
54
|
+
apply_state_to_association lib/active_shepherd/apply_state.rb /^ def apply_state_to_association(association_reflection, state)$/;" f class:ActiveShepherd
|
55
|
+
apply_state_to_associations lib/active_shepherd/apply_state.rb /^ def apply_state_to_associations$/;" f class:ActiveShepherd
|
56
|
+
apply_state_to_has_many_association lib/active_shepherd/apply_state.rb /^ def apply_state_to_has_many_association(association_reflection, foreign_key, state_set)$/;" f class:ActiveShepherd
|
57
|
+
apply_state_to_has_one_association lib/active_shepherd/apply_state.rb /^ def apply_state_to_has_one_association(association_reflection, foreign_key, state)$/;" f class:ActiveShepherd
|
58
|
+
apply_state_to_root_model lib/active_shepherd/apply_state.rb /^ def apply_state_to_root_model$/;" f class:ActiveShepherd
|
59
|
+
association_state lib/active_shepherd/query_state.rb /^ def association_state(name, association_reflection)$/;" f class:ActiveShepherd
|
60
|
+
associations lib/active_shepherd/aggregate.rb /^ def associations$/;" f class:ActiveShepherd
|
61
|
+
associations lib/active_shepherd/state_method.rb /^ def associations$/;" f class:ActiveShepherd
|
62
|
+
attributes lib/active_shepherd/state_method.rb /^ def attributes$/;" f class:ActiveShepherd
|
63
|
+
behave_like_an_aggregate? lib/active_shepherd/aggregate_root.rb /^ def behave_like_an_aggregate?$/;" f class:ActiveShepherd.ClassMethods
|
64
|
+
build_persisted_state test/integration/project_todo_scenario_test.rb /^ def build_persisted_state$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
65
|
+
changes lib/active_shepherd/aggregate.rb /^ def changes$/;" f class:ActiveShepherd
|
66
|
+
changes= lib/active_shepherd/aggregate.rb /^ def changes=(hash)$/;" f class:ActiveShepherd
|
67
|
+
changes_for_associated_model lib/active_shepherd/query_changes.rb /^ def changes_for_associated_model(model, foreign_key)$/;" f class:ActiveShepherd
|
68
|
+
deep_reverse_changes lib/active_shepherd.rb /^ def self.deep_reverse_changes(changes)$/;" F class:ActiveShepherd
|
69
|
+
default_attributes lib/active_shepherd/aggregate.rb /^ def default_attributes$/;" f class:ActiveShepherd
|
70
|
+
deserialize_value lib/active_shepherd/aggregate.rb /^ def deserialize_value(attribute_name, value)$/;" f class:ActiveShepherd
|
71
|
+
dump test/setup_test_models.rb /^ def self.dump(fruit)$/;" F class:Project
|
72
|
+
enable lib/active_shepherd/active_record_shim.rb /^ def self.enable!(activerecord_base)$/;" F class:ActiveShepherd
|
73
|
+
handle_create_or_destroy_keys lib/active_shepherd/apply_changes.rb /^ def handle_create_or_destroy_keys$/;" f class:ActiveShepherd
|
74
|
+
included lib/active_shepherd/aggregate_root.rb /^ def self.included(base)$/;" F class:ActiveShepherd
|
75
|
+
inherited lib/active_shepherd/state_method.rb /^ def self.inherited(base)$/;" F class:ActiveShepherd
|
76
|
+
initialize lib/active_shepherd/aggregate.rb /^ def initialize(model, excluded_attributes = [])$/;" f class:ActiveShepherd
|
77
|
+
initialize lib/active_shepherd/state_method.rb /^ def initialize(aggregate, hash = {})$/;" f class:ActiveShepherd
|
78
|
+
load test/setup_test_models.rb /^ def self.load(blob)$/;" F class:Project
|
79
|
+
mark_all_associated_objects_for_destruction lib/active_shepherd/apply_state.rb /^ def mark_all_associated_objects_for_destruction$/;" f class:ActiveShepherd
|
80
|
+
query_changes lib/active_shepherd/query_changes.rb /^ def query_changes$/;" f class:ActiveShepherd
|
81
|
+
query_state lib/active_shepherd/query_state.rb /^ def query_state$/;" f class:ActiveShepherd
|
82
|
+
reverse lib/active_shepherd/deep_reverse_changes.rb /^ def reverse$/;" f class:ActiveShepherd
|
83
|
+
reverse_aggregate_changes= lib/active_shepherd/aggregate_root.rb /^ def reverse_aggregate_changes=(changes)$/;" f class:ActiveShepherd
|
84
|
+
reverse_changes test/integration/project_todo_scenario_test.rb /^ def reverse_changes$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
85
|
+
run_through_serializer lib/active_shepherd/aggregate.rb /^ def run_through_serializer(attribute_name, value, method)$/;" f class:ActiveShepherd
|
86
|
+
serialize_value lib/active_shepherd/aggregate.rb /^ def serialize_value(attribute_name, value)$/;" f class:ActiveShepherd
|
87
|
+
set_create_or_destroy_keys lib/active_shepherd/query_changes.rb /^ def set_create_or_destroy_keys$/;" f class:ActiveShepherd
|
88
|
+
setup test/integration/project_todo_scenario_test.rb /^ def setup$/;" f class:IntegrationTest
|
89
|
+
split_hash lib/active_shepherd/state_method.rb /^ def split_hash$/;" f class:ActiveShepherd
|
90
|
+
state lib/active_shepherd/aggregate.rb /^ def state$/;" f class:ActiveShepherd
|
91
|
+
state= lib/active_shepherd/aggregate.rb /^ def state=(hash)$/;" f class:ActiveShepherd
|
92
|
+
state_of_associated_model lib/active_shepherd/query_state.rb /^ def state_of_associated_model(model, foreign_key)$/;" f class:ActiveShepherd
|
93
|
+
state_setter_can_set_timestamps test/integration/project_todo_scenario_test.rb /^ def state_setter_can_set_timestamps$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
94
|
+
test_all_changes_to_associated_objects_show_up_in_aggregate_changes test/integration/project_todo_scenario_test.rb /^ def test_all_changes_to_associated_objects_show_up_in_aggregate_changes$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
95
|
+
test_applying_changes_shows_up_in_model_and_its_associations test/integration/project_todo_scenario_test.rb /^ def test_applying_changes_shows_up_in_model_and_its_associations$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
96
|
+
test_applying_reverse_changes_invokes_apply_change_on_the_reverse_hash test/integration/project_todo_scenario_test.rb /^ def test_applying_reverse_changes_invokes_apply_change_on_the_reverse_hash$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
97
|
+
test_changes_getter_ignores_foreign_key_relationship_to_parent_object test/integration/project_todo_scenario_test.rb /^ def test_changes_getter_ignores_foreign_key_relationship_to_parent_object$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
98
|
+
test_does_not_walk_associations_to_other_entities test/integration/project_todo_scenario_test.rb /^ def test_does_not_walk_associations_to_other_entities$/;" f class:IntegrationTest
|
99
|
+
test_state_changes_getter_and_setter_respect_serialized_attributes test/integration/project_todo_scenario_test.rb /^ def test_state_changes_getter_and_setter_respect_serialized_attributes$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
100
|
+
test_state_getter_does_not_walk_read_only_associations test/integration/project_todo_scenario_test.rb /^ def test_state_getter_does_not_walk_read_only_associations$/;" f class:IntegrationTest
|
101
|
+
test_state_getter_gets_attributes test/integration/project_todo_scenario_test.rb /^ def test_state_getter_gets_attributes$/;" f class:IntegrationTest
|
102
|
+
test_state_getter_gets_attributes_on_has_one_associated_object test/integration/project_todo_scenario_test.rb /^ def test_state_getter_gets_attributes_on_has_one_associated_object$/;" f class:IntegrationTest
|
103
|
+
test_state_getter_ignores_default_scope_attributes test/integration/project_todo_scenario_test.rb /^ def test_state_getter_ignores_default_scope_attributes$/;" f class:IntegrationTest
|
104
|
+
test_state_getter_ignores_foreign_key_relationship_to_parent_object test/integration/project_todo_scenario_test.rb /^ def test_state_getter_ignores_foreign_key_relationship_to_parent_object$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
105
|
+
test_state_getter_ignores_has_many_through_associations test/integration/project_todo_scenario_test.rb /^ def test_state_getter_ignores_has_many_through_associations$/;" f class:IntegrationTest
|
106
|
+
test_state_getter_rejects_id test/integration/project_todo_scenario_test.rb /^ def test_state_getter_rejects_id$/;" f class:IntegrationTest
|
107
|
+
test_state_getter_rejects_unpopulated_associations test/integration/project_todo_scenario_test.rb /^ def test_state_getter_rejects_unpopulated_associations$/;" f class:IntegrationTest
|
108
|
+
test_state_getter_respects_serialized_attributes test/integration/project_todo_scenario_test.rb /^ def test_state_getter_respects_serialized_attributes$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
109
|
+
test_state_getter_symbolizes_all_keys test/integration/project_todo_scenario_test.rb /^ def test_state_getter_symbolizes_all_keys$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
110
|
+
test_state_setter_does_not_walk_read_only_associations test/integration/project_todo_scenario_test.rb /^ def test_state_setter_does_not_walk_read_only_associations$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations
|
111
|
+
test_state_setter_ignores_has_many_through_associations test/integration/project_todo_scenario_test.rb /^ def test_state_setter_ignores_has_many_through_associations$/;" f class:IntegrationTest
|
112
|
+
test_state_setter_marks_existing_associations_for_deletion test/integration/project_todo_scenario_test.rb /^ def test_state_setter_marks_existing_associations_for_deletion$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
113
|
+
test_state_setter_populates_object_graph test/integration/project_todo_scenario_test.rb /^ def test_state_setter_populates_object_graph$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
114
|
+
test_state_setter_resets_unsupplied_attributes_to_default test/integration/project_todo_scenario_test.rb /^ def test_state_setter_resets_unsupplied_attributes_to_default$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
115
|
+
test_state_setter_respects_serialized_attributes test/integration/project_todo_scenario_test.rb /^ def test_state_setter_respects_serialized_attributes$/;" f class:IntegrationTest.test_state_getter_does_not_walk_read_only_associations.test_state_setter_does_not_walk_read_only_associations
|
116
|
+
test_state_setter_sets_attributes test/integration/project_todo_scenario_test.rb /^ def test_state_setter_sets_attributes$/;" f class:IntegrationTest
|
117
|
+
test_state_setter_sets_attributes_on_has_many_associated_object test/integration/project_todo_scenario_test.rb /^ def test_state_setter_sets_attributes_on_has_many_associated_object$/;" f class:IntegrationTest
|
118
|
+
test_state_setter_sets_attributes_on_has_one_associated_object test/integration/project_todo_scenario_test.rb /^ def test_state_setter_sets_attributes_on_has_one_associated_object$/;" f class:IntegrationTest
|
119
|
+
traversable_associations lib/active_shepherd/aggregate.rb /^ def traversable_associations$/;" f class:ActiveShepherd
|
120
|
+
traverse_association? lib/active_shepherd/aggregate.rb /^ def traverse_association?(association)$/;" f class:ActiveShepherd
|
121
|
+
untraversable_association_names lib/active_shepherd/aggregate.rb /^ def untraversable_association_names$/;" f class:ActiveShepherd
|
122
|
+
untraversable_associations lib/active_shepherd/aggregate.rb /^ def untraversable_associations$/;" f class:ActiveShepherd
|
123
|
+
valid_aggregate_changes? lib/active_shepherd/aggregate_root.rb /^ def valid_aggregate_changes?(changes)$/;" f class:ActiveShepherd
|