activeshepherd 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|