hecks-domain 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +5 -5
  2. data/lib/hecks/domain/commands/generate.rb +98 -0
  3. data/lib/hecks/domain/commands.rb +1 -0
  4. data/lib/hecks/domain/generators/domain.rb +21 -0
  5. data/lib/hecks/domain/generators/domain_files.rb +28 -0
  6. data/lib/hecks/domain/generators/entity.rb +30 -0
  7. data/lib/hecks/domain/generators/operation.rb +32 -0
  8. data/lib/hecks/domain/generators/root.rb +30 -0
  9. data/lib/hecks/domain/generators/spec.rb +30 -0
  10. data/lib/hecks/domain/generators/value_object.rb +30 -0
  11. data/lib/hecks/domain/generators.rb +7 -0
  12. data/lib/hecks/domain/parser/aggregate.rb +44 -0
  13. data/lib/hecks/domain/parser/domain_object.rb +123 -0
  14. data/lib/hecks/domain/parser/entity_field.rb +55 -0
  15. data/lib/hecks/domain/parser/fields.rb +16 -0
  16. data/lib/hecks/domain/parser/list_field.rb +13 -0
  17. data/lib/hecks/domain/parser/operation.rb +15 -0
  18. data/lib/hecks/domain/parser/reference_field.rb +12 -0
  19. data/lib/hecks/domain/parser/spec_helper.rb +0 -0
  20. data/lib/hecks/domain/parser/value_field.rb +48 -0
  21. data/lib/hecks/domain/parser.rb +95 -0
  22. data/lib/hecks/domain/support/string.rb +9 -0
  23. data/lib/hecks/domain/support.rb +1 -0
  24. data/lib/hecks/domain/templates/%domain_name%.gemspec.tt +12 -0
  25. data/lib/hecks/domain/templates/%folder_name%/Domainfile.tt +9 -0
  26. data/lib/hecks/domain/templates/%folder_name%/events/command_will_run.rb.tt +11 -0
  27. data/lib/hecks/domain/templates/%folder_name%/spec/spec_helper.rb.tt +1 -0
  28. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%/commands.rb.tt +11 -0
  29. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%/events.rb.tt +11 -0
  30. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%/factories/build.rb.tt +37 -0
  31. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%/factories.rb.tt +11 -0
  32. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%/invariants.rb.tt +11 -0
  33. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%/queries.rb.tt +11 -0
  34. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%/repository.rb.tt +68 -0
  35. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%/subscribers.rb.tt +11 -0
  36. data/lib/hecks/domain/templates/entity/%aggregate_name%/%domain_object_name%.rb.tt +34 -0
  37. data/lib/hecks/domain/templates/lib/%domain_name%.rb.tt +9 -0
  38. data/lib/hecks/domain/templates/lib/support/commands/command_loader.rb +18 -0
  39. data/lib/hecks/domain/templates/lib/support/commands/command_runner.rb +17 -0
  40. data/lib/hecks/domain/templates/lib/support/commands.rb +2 -0
  41. data/lib/hecks/domain/templates/lib/support/domain_object.rb +25 -0
  42. data/lib/hecks/domain/templates/lib/support/events/domain_event.rb +14 -0
  43. data/lib/hecks/domain/templates/lib/support/events/domain_event_publisher.rb +34 -0
  44. data/lib/hecks/domain/templates/lib/support/events.rb +14 -0
  45. data/lib/hecks/domain/templates/lib/support/factories/factory_loader.rb +21 -0
  46. data/lib/hecks/domain/templates/lib/support/factories.rb +1 -0
  47. data/lib/hecks/domain/templates/lib/support/invariants/invariant_loader.rb +24 -0
  48. data/lib/hecks/domain/templates/lib/support/queries/query_loader.rb +18 -0
  49. data/lib/hecks/domain/templates/lib/support/queries.rb +1 -0
  50. data/lib/hecks/domain/templates/lib/support/repositories/repository_loader.rb +32 -0
  51. data/lib/hecks/domain/templates/lib/support/root.rb +27 -0
  52. data/lib/hecks/domain/templates/lib/support/support/string.rb +9 -0
  53. data/lib/hecks/domain/templates/lib/support.rb +11 -0
  54. data/lib/hecks/domain/templates/operation/%aggregate_name%/%domain_object_name%/commands/%operation_name%.rb.tt +21 -0
  55. data/lib/hecks/domain/templates/root/%aggregate_name%/root.rb.tt +14 -0
  56. data/lib/hecks/domain/templates/spec/%aggregate_name%/%root_name%_spec.rb.tt +12 -0
  57. data/lib/hecks/domain/templates/value_object/%aggregate_name%/%domain_object_name%/factories/build.rb.tt +37 -0
  58. data/lib/hecks/domain/templates/value_object/%aggregate_name%/%domain_object_name%/factories.rb.tt +11 -0
  59. data/lib/hecks/domain/templates/value_object/%aggregate_name%/%domain_object_name%.rb.tt +34 -0
  60. data/lib/hecks/domain/top_level_methods.rb +3 -0
  61. data/lib/hecks/domain.rb +21 -0
  62. metadata +87 -42
  63. data/lib/cli/builder/aggregate_command_line_builder.rb +0 -21
  64. data/lib/cli/builder/builder.rb +0 -3
  65. data/lib/cli/builder/reference_command_line_builder.rb +0 -22
  66. data/lib/cli/builder/value_object_command_line_builder.rb +0 -22
  67. data/lib/cli/cli.rb +0 -8
  68. data/lib/cli/command_builder.rb +0 -65
  69. data/lib/cli/domain_object/assignment_template.rb +0 -42
  70. data/lib/cli/domain_object/option_formatter.rb +0 -35
  71. data/lib/cli/generate_domain_object.rb +0 -70
  72. data/lib/cli/new.rb +0 -49
  73. data/lib/cli/templates/aggregate/lib/domain/%name%/%head_name%.rb.tt +0 -16
  74. data/lib/cli/templates/aggregate/lib/domain/%name%/%name%.rb.tt +0 -9
  75. data/lib/cli/templates/aggregate/lib/domain/%name%/repository.rb.tt +0 -38
  76. data/lib/cli/templates/domain/%name%.gemspec.tt +0 -12
  77. data/lib/cli/templates/domain/Version +0 -1
  78. data/lib/cli/templates/domain/lib/%name%.rb.tt +0 -21
  79. data/lib/cli/templates/domain/spec/spec_helper.rb.tt +0 -4
  80. data/lib/cli/templates/reference/lib/domain/%module_name%/%file_name%.rb.tt +0 -25
  81. data/lib/cli/templates/value_object/lib/domain/%module_name%/%name%.rb.tt +0 -24
  82. data/lib/domain_builder/attribute.rb +0 -61
  83. data/lib/domain_builder/domain.rb +0 -16
  84. data/lib/domain_builder/domain_module.rb +0 -32
  85. data/lib/domain_builder/domain_object.rb +0 -44
  86. data/lib/domain_builder/head.rb +0 -5
  87. data/lib/domain_builder/hecks-domain-builder.rb +0 -37
  88. data/lib/domain_builder/reference.rb +0 -16
  89. data/lib/domain_builder/value.rb +0 -5
  90. data/lib/hecks-domain.rb +0 -4
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'parser/aggregate'
4
+ require_relative 'parser/domain_object'
5
+ require_relative 'parser/value_field'
6
+ require_relative 'parser/entity_field'
7
+ require_relative 'parser/list_field'
8
+ require_relative 'parser/operation'
9
+ require_relative 'parser/reference_field'
10
+ require_relative 'parser/fields'
11
+
12
+ class HecksDomain
13
+ class Parser
14
+ attr_reader :name, :aggregates, :spec_helper, :string_support,
15
+ :repository_helper, :factory_loader
16
+
17
+ def initialize(name, &block)
18
+ @name = name
19
+ @aggregates = []
20
+ @domain_version = nil
21
+ instance_eval(&block)
22
+ end
23
+
24
+ def summary(value)
25
+ @summary = value
26
+ end
27
+
28
+ def description(value)
29
+ @description = value
30
+ end
31
+
32
+ def version(value)
33
+ @version = value
34
+ end
35
+
36
+ def gemspec
37
+ {
38
+ summary: @summary,
39
+ description: @description,
40
+ version: @version,
41
+ authors: @authors,
42
+ email: @email,
43
+ homepage: @homepage
44
+ }
45
+ end
46
+
47
+ def authors(value)
48
+ @authors = value
49
+ end
50
+
51
+ def email(value)
52
+ @email = value
53
+ end
54
+
55
+ def homepage(value)
56
+ @homepage = value
57
+ end
58
+
59
+ def aggregate(name, &block)
60
+ @aggregates << Aggregate.new(name, self, &block)
61
+ end
62
+
63
+ def binding
64
+ super
65
+ end
66
+
67
+ def file_name
68
+ @file_name = folder_name + '.rb'
69
+ end
70
+
71
+ def folder_name
72
+ @folder_name = @name.to_s.underscore
73
+ end
74
+
75
+ def domain_version(value)
76
+ @domain_version = value
77
+ end
78
+
79
+ def for_each_domain_object
80
+ aggregates.each do |aggregate|
81
+ aggregate.domain_objects.each do |domain_object|
82
+ yield aggregate, domain_object
83
+ end
84
+ end
85
+ end
86
+
87
+ def for_each_operation
88
+ for_each_domain_object do |aggregate, domain_object|
89
+ domain_object.operations_get.each do |operation|
90
+ yield aggregate, domain_object, operation
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def underscore
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_").
7
+ downcase
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ require_relative 'support/string'
@@ -0,0 +1,12 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = '<%= domain_name %>'
3
+ s.version = '<%= gemspec[:version] %>'
4
+ s.licenses = ['MIT']
5
+ s.summary = '<%= gemspec[:summary] %>'
6
+ s.description = '<%= gemspec[:description] %>'
7
+ s.authors = <%= gemspec[:authors] %>
8
+ s.email = '<%= gemspec[:email] %>'
9
+ s.files = Dir['lib/**/*.rb', 'domain/**/*.rb', 'events/**/*.rb', 'Domainfile']
10
+ s.homepage = '<%= gemspec[:homepage] %>'
11
+ s.metadata = { 'hecks_domain' => 'true' }
12
+ end
@@ -0,0 +1,9 @@
1
+ domain(:<%= domain_name %>) do
2
+ summary '<FILL ME IN>'
3
+ description '<FILL ME IN>'
4
+ version '0.0.1'
5
+ authors ['<FILL ME IN>']
6
+ email '<FILL ME IN>'
7
+ homepage 'http://www.example.com'
8
+ domain_version '0.1.0'
9
+ end
@@ -0,0 +1,11 @@
1
+ module <%= domain_name %>
2
+ module Events
3
+ class CommandWillRun
4
+ attr_reader :root, :args, :command_to_run
5
+ def initialize(command)
6
+ @root = command.root
7
+ @command_to_run = command
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1 @@
1
+ require_relative '../lib/<%= domain_name.underscore %>'
@@ -0,0 +1,11 @@
1
+ Dir[File.dirname(__FILE__) + '/commands/*.rb'].each {|file| require_relative file }
2
+ module <%= @domain.name %>
3
+ module Domain
4
+ module <%= @aggregate.name %>
5
+ class <%= @domain_object.name %>
6
+ module Commands
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ Dir[File.dirname(__FILE__) + '/events/*.rb'].each { |file| require_relative file }
2
+ module <%= domain.name %>
3
+ module Domain
4
+ module <%= aggregate.name %>
5
+ class <%= domain_object.name %>
6
+ module Events
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ module <%= @domain.name %>
2
+ module Domain
3
+ module <%= @aggregate.name%>
4
+ class <%= @domain_object.name %>
5
+ module Factories
6
+ # Recursively build domain objects. Used in the domain as the primary
7
+ # factory. The results of #build can be passed to any other build
8
+ # factory in the domain. Takes a hash, or a list of hashes. If a list
9
+ # is given, it will return a list of the instantiated objects
10
+ class Build
11
+ def self.factory(args=nil)
12
+ return args if args.nil?
13
+ return args unless args.is_a?(Hash)
14
+
15
+ [args].flatten.map do |domain_object_args|
16
+ new_domain_object(domain_object_args)
17
+ end.tap do |result|
18
+ return result.first unless args.is_a?(Array)
19
+ end
20
+ end
21
+
22
+ def self.new_domain_object(args)
23
+ <%= @domain_object.name %>.new(
24
+ args.merge(
25
+ <% @domain_object.fields.each do |field| -%>
26
+ <% next unless (field.respond_to?(:module_name) && field.module_name) -%>
27
+ <%= field.name.to_s%>: <%= field.module_name.is_a?(Hash) ? 'Domain::' + field.module_name.to_a.join('::').to_s : field.module_name.to_s %>.build(args[:<%= field.name.to_s%>]<%= ' || []' if field.is_a?(HecksDomain::Parser::ListField) %>),
28
+ <% end -%>
29
+ )
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ Dir[File.dirname(__FILE__) + '/factories/*.rb'].each {|file| require_relative file }
2
+ module <%= domain.name %>
3
+ module Domain
4
+ module <%= aggregate.name %>
5
+ class <%= domain_object.name %>
6
+ module Factories
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ Dir[File.dirname(__FILE__) + '/invariants/*.rb'].each {|file| require_relative file }
2
+ module <%= domain.name %>
3
+ module Domain
4
+ module <%= aggregate.name %>
5
+ class <%= domain_object.name %>
6
+ module Invariants
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ Dir[File.dirname(__FILE__) + '/queries/*.rb'].each { |file| require_relative file }
2
+ module <%= domain.name %>
3
+ module Domain
4
+ module <%= aggregate.name %>
5
+ class <%= domain_object.name %>
6
+ module Queries
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,68 @@
1
+
2
+ module <%= domain.name %>
3
+ module Domain
4
+ module <%= aggregate.name %>
5
+ class <%= domain_object.name %>
6
+ class Repository
7
+ include Singleton
8
+ def self.save(object)
9
+ instance.save(object)
10
+ end
11
+
12
+ def self.fetch(<%= domain_object_name %>)
13
+ instance.fetch(<%= domain_object_name %>)
14
+ end
15
+
16
+ def initialize
17
+ @objects = {}
18
+ end
19
+
20
+ def self.create(<%= domain_object_name %>)
21
+ instance.create(<%= domain_object_name %>)
22
+ end
23
+
24
+ def self.all
25
+ instance.all
26
+ end
27
+
28
+ def self.destroy(<%= domain_object_name %>)
29
+ instance.destroy(<%= domain_object_name %>)
30
+ end
31
+
32
+ def all
33
+ @objects.values
34
+ end
35
+
36
+ def destroy(<%= domain_object_name %>)
37
+ @objects.delete(<%= domain_object_name %>.id)
38
+ end
39
+
40
+ def create(<%= domain_object_name %>)
41
+ klass = self.class.const_get(
42
+ self.class.to_s.gsub('::Repository', '')
43
+ )
44
+ domain_object = klass.build(<%= domain_object_name %>)
45
+ domain_object.tap(&:save)
46
+ end
47
+
48
+ def fetch(fetchable)
49
+ return @objects[fetchable.id] if fetchable.respond_to?(:id)
50
+
51
+ @objects[fetchable]
52
+ end
53
+
54
+ def save(<%= domain_object_name %>)
55
+ domain_object = <%= domain_object_name %>
56
+ @objects[<%= domain_object_name %>.hash] = domain_object
57
+
58
+ <%= domain_object_name %>.instance_eval do
59
+ @id = <%= domain_object_name %>.hash
60
+ end
61
+
62
+ <%= domain_object_name %>
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,11 @@
1
+ Dir[File.dirname(__FILE__) + '/subscribers/*.rb'].each { |file| require_relative file }
2
+ module <%= @domain.name %>
3
+ module Domain
4
+ module <%= aggregate.name %>
5
+ class <%= domain_object.name %>
6
+ module Subscribers
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ module <%= domain.name %>
2
+ module Domain
3
+ module <%= aggregate.name %>
4
+ class <%= domain_object.name %>
5
+ <%= 'include Support::Root' if domain_object.is_a?(HecksDomain::Parser::Root) %>
6
+ include Support::DomainObject
7
+
8
+ attr_reader <%= domain_object.public_accessors %>
9
+
10
+ def initialize(<%= domain_object.initializer_attributes %>)
11
+ <% domain_object.fields.each do |field| -%>
12
+ <%= "@#{field.name} = #{field.initial_state}" %>
13
+ <% end -%>
14
+ end
15
+ <% domain_object.boolean_accessors.each do |field| -%>
16
+
17
+ def <%= field.name %>?
18
+ @<%= field.name %>
19
+ end
20
+ <% end -%>
21
+ <% domain_object.list_accessors.each do |field| -%>
22
+
23
+ def <%= field.name %>
24
+ @<%= field.name %>.clone.freeze
25
+ end
26
+ <% end -%>
27
+
28
+ private
29
+
30
+ attr_writer <%= domain_object.private_accessors %>
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'support'
2
+ Dir[File.dirname(__FILE__) + "/../events/*.rb"].each { |file| require_relative file }
3
+ <% domain.aggregates.each do |aggregate| -%>
4
+ require_relative '../domain/<%= aggregate.folder_name %>/root'
5
+ <% end -%>
6
+
7
+ module <%= domain.name %>
8
+ class InvariantViolationError < StandardError; end
9
+ end
@@ -0,0 +1,18 @@
1
+ class Support
2
+ module Commands
3
+ module CommandLoader
4
+ def self.included(base)
5
+ return unless base.constants.include?(:Commands)
6
+ base::Commands.constants.each do |constant|
7
+ base.class_eval "
8
+ def #{constant.to_s.underscore}!(*args, &block)
9
+ Support::Commands::CommandRunner.run(
10
+ Commands::#{constant}.new(self, *args), &block
11
+ )
12
+ end
13
+ "
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ class Support
2
+ module Commands
3
+ module CommandRunner
4
+ def self.run(command, &block)
5
+ Events::DomainEventPublisher.emit(
6
+ const_get(command.class.to_s.split('::')[0])::
7
+ Events::CommandWillRun.new(command)
8
+ )
9
+
10
+ command.call
11
+ command.root.test_invariants(command)
12
+ Events::DomainEventPublisher.emit(command, &block)
13
+ command
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'commands/command_runner'
2
+ require_relative 'commands/command_loader'
@@ -0,0 +1,25 @@
1
+ class Support
2
+ module DomainObject
3
+ TYPES = %w[services invariants factories].freeze
4
+
5
+ LOADERS = [
6
+ Support::Factories::FactoryLoader, Support::Invariants::InvariantLoader
7
+ ].freeze
8
+
9
+ def self.included(base)
10
+ path = [
11
+ '../../domain',
12
+ base.to_s.split('::')[-2].underscore.downcase,
13
+ base.to_s.split('::')[-1].underscore.downcase
14
+ ].join('/')
15
+
16
+ TYPES.each do |name|
17
+ Dir[File.dirname(__FILE__) + "/#{path}/" + name + '/*.rb'].each do |file|
18
+ require_relative file
19
+ end
20
+ end
21
+
22
+ LOADERS.each { |loader| base.include(loader) }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ class Support
2
+ module Events
3
+ class DomainEvent
4
+ attr_reader :type, :name, :command, :args, :root
5
+ def initialize(command)
6
+ @command = command
7
+ @root = @command.root
8
+ @type = @command.class
9
+ @name = @type.to_s.underscore
10
+ @args = command.args
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,34 @@
1
+ class Support
2
+ module Events
3
+ class DomainEventPublisher
4
+ include Singleton
5
+ attr_reader :subscribers
6
+ def initialize
7
+ @subscribers = []
8
+ end
9
+
10
+ def self.emit(command, &block)
11
+ instance.emit(DomainEvent.new(command), &block)
12
+ end
13
+
14
+ def self.subscribe(subscriber)
15
+ instance.subscribers << subscriber
16
+ end
17
+
18
+ def self.cancel_subscription(subscriber)
19
+ instance.subscribers.delete(subscriber)
20
+ end
21
+
22
+ def emit(domain_event, &block)
23
+ yield domain_event if block
24
+ @subscribers.each do |subscriber|
25
+ next unless subscriber.domain_event == '*' ||
26
+ subscriber.domain_event == domain_event.type
27
+
28
+ subscriber.notify(domain_event)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,14 @@
1
+ require_relative 'events/domain_event_publisher'
2
+ require_relative 'events/domain_event'
3
+
4
+ class Support
5
+ module Events
6
+ def self.subscribe(subscriber)
7
+ DomainEventPublisher.subscribe(subscriber)
8
+ end
9
+
10
+ def self.cancel_subscription(subscriber)
11
+ DomainEventPublisher.cancel_subscription(subscriber)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ class Support
2
+ module Factories
3
+ module FactoryLoader
4
+ def self.included(base)
5
+ return unless base.constants.include?(:Factories)
6
+ base::Factories.constants.each do |constant|
7
+ base.class_eval "
8
+ def #{constant.to_s.underscore}(*args)
9
+ #{base}::Factories::#{constant}.factory(self, *args)
10
+ end
11
+ "
12
+ base.instance_eval "
13
+ def #{constant.to_s.underscore}(*args)
14
+ #{base}::Factories::#{constant}.factory(*args)
15
+ end
16
+ "
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1 @@
1
+ require_relative 'factories/factory_loader'
@@ -0,0 +1,24 @@
1
+ class Support
2
+ module Invariants
3
+ module InvariantLoader
4
+ def self.included(base)
5
+ return unless base.constants.include?(:Invariants)
6
+ base::Invariants.constants.each do |invariant|
7
+ base.include base::Invariants.const_get(invariant)
8
+ end
9
+ end
10
+
11
+ def test_invariants(command = nil)
12
+ return unless self.class.constants.include?(:Invariants)
13
+ self.class::Invariants.constants.each do |invariant|
14
+ invariant_class = self.class::Invariants.const_get(invariant)
15
+ invariant_class.instance_methods(false).each do |method|
16
+ raise "invariant methods must be prepended with \"invariant_test\". Try:\n" +
17
+ "#{invariant_class}#invariant_test_#{method.to_s}" unless method.to_s =~ /^invariant.*/
18
+ send(method, command)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ class Support
2
+ module Queries
3
+ module QueryLoader
4
+ def self.included(base)
5
+ return unless base.constants.include?(:Queries)
6
+ base::Queries.constants.each do |constant|
7
+ raise "Query name `#{constant}` not valid. Query classes must start with 'Find'" unless constant.to_s.underscore =~ /^find_.*/
8
+
9
+ base.class_eval "
10
+ def #{constant.to_s.underscore}(*args, &block)
11
+ Queries::#{constant}.query(self, *args)
12
+ end
13
+ "
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1 @@
1
+ require_relative 'queries/query_loader'
@@ -0,0 +1,32 @@
1
+ class Support
2
+ module Repositories
3
+ module RepositoryLoader
4
+ def self.included(base)
5
+ base.class_eval do
6
+ def save
7
+ test_invariants
8
+ self.class::Repository.save(self)
9
+ end
10
+
11
+ def destroy
12
+ self.class::Repository.destroy(self)
13
+ end
14
+ end
15
+
16
+ base.instance_eval do
17
+ def create(domain_object = nil)
18
+ self::Repository.create(domain_object).tap(&:test_invariants)
19
+ end
20
+
21
+ def fetch(fetchable)
22
+ self::Repository.fetch(fetchable)
23
+ end
24
+
25
+ def all
26
+ self::Repository.all
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,27 @@
1
+ class Support
2
+ module Root
3
+ TYPES = %w[commands services invariants queries events subscribers].freeze
4
+
5
+ LOADERS = [
6
+ Support::Commands::CommandLoader, Support::Queries::QueryLoader,
7
+ Support::Repositories::RepositoryLoader
8
+ ].freeze
9
+
10
+ def self.included(base)
11
+ path = [
12
+ '../../domain',
13
+ base.to_s.split('::')[-2].underscore.downcase,
14
+ base.to_s.split('::')[-1].underscore.downcase
15
+ ].join('/')
16
+
17
+ require_relative path + '/repository'
18
+
19
+ TYPES.each do |name|
20
+ Dir[File.dirname(__FILE__) + "/#{path}/" + name + '/*.rb']
21
+ .each { |file| require_relative file }
22
+ end
23
+
24
+ LOADERS.each { |loader| base.include(loader) }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def underscore
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_").
7
+ downcase
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require 'singleton'
2
+ require_relative 'support/repositories/repository_loader'
3
+ require_relative 'support/support/string'
4
+ require_relative 'support/events'
5
+ require_relative 'support/commands'
6
+ require_relative 'support/queries'
7
+ require_relative 'support/factories'
8
+ require_relative 'support/invariants/invariant_loader'
9
+ require_relative 'support/queries/query_loader'
10
+ require_relative 'support/root'
11
+ require_relative 'support/domain_object'