rddd 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/lib/rddd.rb +16 -2
- data/lib/rddd/aggregate_root.rb +8 -6
- data/lib/rddd/aggregate_root_finders.rb +9 -7
- data/lib/rddd/configuration.rb +21 -0
- data/lib/rddd/entity.rb +1 -1
- data/lib/rddd/repository.rb +1 -1
- data/lib/rddd/repository_factory.rb +16 -12
- data/lib/rddd/service.rb +1 -1
- data/lib/rddd/service_bus.rb +50 -48
- data/lib/rddd/service_factory.rb +13 -8
- data/lib/rddd/version.rb +1 -1
- data/spec/integration_spec.rb +3 -3
- data/spec/lib/aggregate_root_spec.rb +6 -6
- data/spec/lib/entity_spec.rb +4 -4
- data/spec/lib/repository_factory_spec.rb +16 -6
- data/spec/lib/repository_spec.rb +1 -1
- data/spec/lib/service_bus_spec.rb +7 -7
- data/spec/lib/service_factory_spec.rb +15 -5
- data/spec/lib/service_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -0
- metadata +2 -1
data/Gemfile.lock
CHANGED
data/lib/rddd.rb
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
-
require
|
1
|
+
require 'rddd/version'
|
2
|
+
require 'rddd/configuration'
|
2
3
|
|
3
|
-
module Rddd
|
4
|
+
module Rddd
|
5
|
+
#
|
6
|
+
# Configure Rddd framework.
|
7
|
+
#
|
8
|
+
# ## Usage
|
9
|
+
#
|
10
|
+
# Rddd.configure do |config|
|
11
|
+
# config.services_namespace = Rddd::Services
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
def self.configure
|
15
|
+
yield(Rddd::Configuration.instance)
|
16
|
+
end
|
17
|
+
end
|
data/lib/rddd/aggregate_root.rb
CHANGED
@@ -2,14 +2,16 @@ require 'rddd/entity'
|
|
2
2
|
require 'rddd/repository_factory'
|
3
3
|
require 'rddd/aggregate_root_finders'
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
module Rddd
|
6
|
+
class AggregateRoot < Entity
|
7
|
+
extend AggregateRootFinders
|
7
8
|
|
8
|
-
|
9
|
+
finder :find_by_id
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
[:create, :update, :delete].each do |action|
|
12
|
+
define_method action do
|
13
|
+
self.class.repository.send(action, self)
|
14
|
+
end
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -1,11 +1,13 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Rddd
|
2
|
+
module AggregateRootFinders
|
3
|
+
def finder(name)
|
4
|
+
define_singleton_method name do |*args|
|
5
|
+
repository.send(name, *args)
|
6
|
+
end
|
5
7
|
end
|
6
|
-
end
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
def repository
|
10
|
+
RepositoryFactory.build(self)
|
11
|
+
end
|
10
12
|
end
|
11
13
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Use configuration to configure internals of the RDDD
|
5
|
+
# framework.
|
6
|
+
#
|
7
|
+
module Rddd
|
8
|
+
class Configuration
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
attr_writer :services_namespace, :repositories_namespace
|
12
|
+
|
13
|
+
def services_namespace
|
14
|
+
@services_namespace || Object
|
15
|
+
end
|
16
|
+
|
17
|
+
def repositories_namespace
|
18
|
+
@repositories_namespace || Object
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/rddd/entity.rb
CHANGED
data/lib/rddd/repository.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
1
1
|
require 'rddd/repository'
|
2
|
+
require 'rddd/configuration'
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
module Rddd
|
5
|
+
class NotExistingRepository < RuntimeError
|
6
|
+
end
|
5
7
|
|
6
|
-
class RepositoryFactory
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
begin
|
11
|
-
repository = const_get(repository_name)
|
12
|
-
rescue
|
13
|
-
raise NotExistingRepository unless repository
|
14
|
-
end
|
8
|
+
class RepositoryFactory
|
9
|
+
def self.build(clazz)
|
10
|
+
repository_name = "#{clazz.name.split('::').last}Repository"
|
11
|
+
ns = Configuration.instance.repositories_namespace
|
15
12
|
|
16
|
-
|
13
|
+
begin
|
14
|
+
repository = ns.const_get(repository_name)
|
15
|
+
rescue
|
16
|
+
raise NotExistingRepository unless repository
|
17
|
+
end
|
18
|
+
|
19
|
+
repository.new
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
data/lib/rddd/service.rb
CHANGED
data/lib/rddd/service_bus.rb
CHANGED
@@ -1,57 +1,59 @@
|
|
1
1
|
require 'rddd/service_factory'
|
2
2
|
|
3
|
-
|
3
|
+
module Rddd
|
4
|
+
class InvalidService < RuntimeError; end
|
4
5
|
|
5
|
-
#
|
6
|
-
# Service bus is the central entry point for execution of service within the
|
7
|
-
# domain layer. Unless you have a very good reason, services should not be
|
8
|
-
# instantiated directly outside the domain layer, as you leave the flexibility
|
9
|
-
# on domain itself to choose the correct implementation.
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# ## Usage
|
13
|
-
#
|
14
|
-
# Service bus as the module could be included to any object which intend to
|
15
|
-
# call services within the domain layer.
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# ## Example
|
19
|
-
#
|
20
|
-
# class ProjectsController
|
21
|
-
# include ServiceBus
|
22
|
-
#
|
23
|
-
# def create
|
24
|
-
# execute(:create_project, params) do |errors|
|
25
|
-
# render :new, :errors => errors
|
26
|
-
# return
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# redirect_to projects_path, :notice => 'Project was successfully created!'
|
30
|
-
# end
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
#
|
34
|
-
module ServiceBus
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
6
|
+
#
|
7
|
+
# Service bus is the central entry point for execution of service within the
|
8
|
+
# domain layer. Unless you have a very good reason, services should not be
|
9
|
+
# instantiated directly outside the domain layer, as you leave the flexibility
|
10
|
+
# on domain itself to choose the correct implementation.
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# ## Usage
|
14
|
+
#
|
15
|
+
# Service bus as the module could be included to any object which intend to
|
16
|
+
# call services within the domain layer.
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# ## Example
|
20
|
+
#
|
21
|
+
# class ProjectsController
|
22
|
+
# include ServiceBus
|
23
|
+
#
|
24
|
+
# def create
|
25
|
+
# execute(:create_project, params) do |errors|
|
26
|
+
# render :new, :errors => errors
|
27
|
+
# return
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# redirect_to projects_path, :notice => 'Project was successfully created!'
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
#
|
35
|
+
module ServiceBus
|
36
|
+
#
|
37
|
+
# Execute the given service.
|
38
|
+
#
|
39
|
+
# @param {Symbol} Service to be executed.
|
40
|
+
# @param {Hash} Attributes to be passed to the service call.
|
41
|
+
# @param {Block} Optional error callback block.
|
42
|
+
#
|
43
|
+
def execute(service_name, attributes = {})
|
44
|
+
raise InvalidService unless service = build_service(service_name, attributes)
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
unless service.valid?
|
47
|
+
yield(service.errors) and return if block_given?
|
48
|
+
end
|
48
49
|
|
49
|
-
|
50
|
-
|
50
|
+
service.execute
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
+
private
|
53
54
|
|
54
|
-
|
55
|
-
|
55
|
+
def build_service(service_name, attributes)
|
56
|
+
ServiceFactory.build(service_name, attributes)
|
57
|
+
end
|
56
58
|
end
|
57
59
|
end
|
data/lib/rddd/service_factory.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
-
|
2
|
-
def self.build(name, attributes)
|
3
|
-
class_name = "#{camel_case(name.to_s)}Service"
|
1
|
+
require 'rddd/configuration'
|
4
2
|
|
5
|
-
|
6
|
-
|
3
|
+
module Rddd
|
4
|
+
class ServiceFactory
|
5
|
+
def self.build(name, attributes)
|
6
|
+
class_name = "#{camel_case(name.to_s)}Service"
|
7
|
+
ns = Configuration.instance.services_namespace
|
8
|
+
|
9
|
+
ns.const_get(class_name.to_sym).new(attributes)
|
10
|
+
end
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
12
|
+
def self.camel_case(string)
|
13
|
+
return string if string !~ /_/ && string =~ /[A-Z]+.*/
|
14
|
+
string.split('_').map{|e| e.capitalize}.join
|
15
|
+
end
|
11
16
|
end
|
12
17
|
end
|
data/lib/rddd/version.rb
CHANGED
data/spec/integration_spec.rb
CHANGED
@@ -4,11 +4,11 @@ require 'rddd/aggregate_root'
|
|
4
4
|
require 'rddd/service_bus'
|
5
5
|
require 'rddd/service'
|
6
6
|
|
7
|
-
class Project < AggregateRoot
|
7
|
+
class Project < Rddd::AggregateRoot
|
8
8
|
attr_accessor :name
|
9
9
|
end
|
10
10
|
|
11
|
-
class CreateProjectService < Service
|
11
|
+
class CreateProjectService < Rddd::Service
|
12
12
|
def execute
|
13
13
|
project = Project.new(@attributes[:id])
|
14
14
|
project.name = @attributes[:name]
|
@@ -24,7 +24,7 @@ class ProjectRepository
|
|
24
24
|
end
|
25
25
|
|
26
26
|
class ProjectsController
|
27
|
-
include ServiceBus
|
27
|
+
include Rddd::ServiceBus
|
28
28
|
|
29
29
|
def create(params)
|
30
30
|
execute(:create_project, params)
|
@@ -1,22 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rddd/aggregate_root'
|
3
3
|
|
4
|
-
describe AggregateRoot do
|
4
|
+
describe Rddd::AggregateRoot do
|
5
5
|
let(:id) { stub('id') }
|
6
6
|
|
7
|
-
let(:aggregate_root) { AggregateRoot.new(id) }
|
7
|
+
let(:aggregate_root) { Rddd::AggregateRoot.new(id) }
|
8
8
|
|
9
9
|
it 'should be entity' do
|
10
|
-
aggregate_root.should be_kind_of Entity
|
10
|
+
aggregate_root.should be_kind_of Rddd::Entity
|
11
11
|
end
|
12
12
|
|
13
13
|
describe '#find_by_id' do
|
14
|
-
subject { AggregateRoot.find_by_id(id) }
|
14
|
+
subject { Rddd::AggregateRoot.find_by_id(id) }
|
15
15
|
|
16
16
|
let(:repository) { stub('repository') }
|
17
17
|
|
18
18
|
before {
|
19
|
-
RepositoryFactory.expects(:build).returns(repository)
|
19
|
+
Rddd::RepositoryFactory.expects(:build).returns(repository)
|
20
20
|
repository.expects(:find_by_id).with(id)
|
21
21
|
}
|
22
22
|
|
@@ -30,7 +30,7 @@ describe AggregateRoot do
|
|
30
30
|
let(:repository) { stub('repository') }
|
31
31
|
|
32
32
|
it 'should call #create on repository' do
|
33
|
-
RepositoryFactory.expects(:build).with(AggregateRoot).returns(repository)
|
33
|
+
Rddd::RepositoryFactory.expects(:build).with(Rddd::AggregateRoot).returns(repository)
|
34
34
|
|
35
35
|
repository.expects(action).with(subject)
|
36
36
|
|
data/spec/lib/entity_spec.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rddd/entity'
|
3
3
|
|
4
|
-
describe Entity do
|
4
|
+
describe Rddd::Entity do
|
5
5
|
it 'should have identity' do
|
6
|
-
entity = Entity.new('1234')
|
6
|
+
entity = Rddd::Entity.new('1234')
|
7
7
|
|
8
8
|
entity.id.should == '1234'
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'two entities with same identity are equal' do
|
12
|
-
a = Entity.new('1234')
|
13
|
-
b = Entity.new('1234')
|
12
|
+
a = Rddd::Entity.new('1234')
|
13
|
+
b = Rddd::Entity.new('1234')
|
14
14
|
|
15
15
|
(a == b).should be_true
|
16
16
|
end
|
@@ -2,23 +2,33 @@ require 'spec_helper'
|
|
2
2
|
require 'rddd/entity'
|
3
3
|
require 'rddd/repository_factory'
|
4
4
|
|
5
|
-
describe RepositoryFactory do
|
5
|
+
describe Rddd::RepositoryFactory do
|
6
6
|
describe '.build' do
|
7
|
-
subject { RepositoryFactory.build(Entity) }
|
7
|
+
subject { Rddd::RepositoryFactory.build(Rddd::Entity) }
|
8
8
|
|
9
9
|
context 'with existing repository' do
|
10
|
-
before
|
10
|
+
before do
|
11
|
+
Rddd.const_set(:Repositories, Module.new)
|
12
|
+
Rddd::Repositories.const_set(:EntityRepository, Class.new)
|
11
13
|
|
12
|
-
|
14
|
+
Rddd.configure { |config| config.repositories_namespace = Rddd::Repositories }
|
15
|
+
end
|
16
|
+
|
17
|
+
after do
|
18
|
+
Rddd::Repositories.class_eval {remove_const(:EntityRepository)}
|
19
|
+
Rddd.class_eval {remove_const(:Repositories)}
|
20
|
+
|
21
|
+
Rddd.configure { |config| config.repositories_namespace = Object }
|
22
|
+
end
|
13
23
|
|
14
24
|
it 'should return instance of repository' do
|
15
|
-
should be_kind_of EntityRepository
|
25
|
+
should be_kind_of Rddd::Repositories::EntityRepository
|
16
26
|
end
|
17
27
|
end
|
18
28
|
|
19
29
|
context 'with not existing repository' do
|
20
30
|
it 'should raise NotExistingRepository' do
|
21
|
-
lambda { subject }.should raise_exception NotExistingRepository
|
31
|
+
lambda { subject }.should raise_exception Rddd::NotExistingRepository
|
22
32
|
end
|
23
33
|
end
|
24
34
|
end
|
data/spec/lib/repository_spec.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rddd/service_bus'
|
3
3
|
|
4
|
-
describe ServiceBus do
|
4
|
+
describe Rddd::ServiceBus do
|
5
5
|
let(:attributes) { stub('attributes') }
|
6
6
|
|
7
7
|
let(:controller) do
|
8
|
-
stub('controller').tap { |controller| controller.extend ServiceBus }
|
8
|
+
stub('controller').tap { |controller| controller.extend Rddd::ServiceBus }
|
9
9
|
end
|
10
10
|
|
11
11
|
describe '.execute' do
|
@@ -15,7 +15,7 @@ describe ServiceBus do
|
|
15
15
|
|
16
16
|
context 'existing service' do
|
17
17
|
it do
|
18
|
-
ServiceFactory.expects(:build).with(:foo, attributes).returns(service)
|
18
|
+
Rddd::ServiceFactory.expects(:build).with(:foo, attributes).returns(service)
|
19
19
|
service.expects(:execute)
|
20
20
|
|
21
21
|
subject
|
@@ -24,10 +24,10 @@ describe ServiceBus do
|
|
24
24
|
|
25
25
|
context 'not-existing service' do
|
26
26
|
it do
|
27
|
-
ServiceFactory.expects(:build).with(:foo, attributes).returns(nil)
|
27
|
+
Rddd::ServiceFactory.expects(:build).with(:foo, attributes).returns(nil)
|
28
28
|
service.expects(:execute).never
|
29
29
|
|
30
|
-
lambda { subject }.should raise_exception InvalidService
|
30
|
+
lambda { subject }.should raise_exception Rddd::InvalidService
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -36,7 +36,7 @@ describe ServiceBus do
|
|
36
36
|
before { service.stubs(:valid?).returns(false) }
|
37
37
|
|
38
38
|
it do
|
39
|
-
ServiceFactory.expects(:build).with(:foo, attributes).returns(service)
|
39
|
+
Rddd::ServiceFactory.expects(:build).with(:foo, attributes).returns(service)
|
40
40
|
service.expects(:execute).never
|
41
41
|
|
42
42
|
subject
|
@@ -54,7 +54,7 @@ describe ServiceBus do
|
|
54
54
|
let(:error_block) { lambda {|errors|} }
|
55
55
|
|
56
56
|
it do
|
57
|
-
ServiceFactory.expects(:build).with(:foo, attributes).returns(service)
|
57
|
+
Rddd::ServiceFactory.expects(:build).with(:foo, attributes).returns(service)
|
58
58
|
service.expects(:execute).never
|
59
59
|
|
60
60
|
controller.execute(:foo, attributes, &error_block)
|
@@ -1,18 +1,28 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rddd/service_factory'
|
3
3
|
|
4
|
-
describe ServiceFactory do
|
4
|
+
describe Rddd::ServiceFactory do
|
5
5
|
let(:attributes) { stub('attributes') }
|
6
6
|
|
7
|
-
before
|
7
|
+
before do
|
8
|
+
Rddd.const_set(:Services, Module.new)
|
9
|
+
Rddd::Services.const_set(:CreateProjectService, Class.new)
|
8
10
|
|
9
|
-
|
11
|
+
Rddd.configure { |config| config.services_namespace = Rddd::Services }
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
Rddd::Services.class_eval {remove_const(:CreateProjectService)}
|
16
|
+
Rddd.class_eval {remove_const(:Services)}
|
17
|
+
|
18
|
+
Rddd.configure { |config| config.services_namespace = Object }
|
19
|
+
end
|
10
20
|
|
11
21
|
describe '.build' do
|
12
22
|
it do
|
13
|
-
CreateProjectService.expects(:new).with(attributes)
|
23
|
+
Rddd::Services::CreateProjectService.expects(:new).with(attributes)
|
14
24
|
|
15
|
-
ServiceFactory.build(:create_project, attributes)
|
25
|
+
Rddd::ServiceFactory.build(:create_project, attributes)
|
16
26
|
end
|
17
27
|
end
|
18
28
|
end
|
data/spec/lib/service_spec.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rddd/service'
|
3
3
|
|
4
|
-
describe Service do
|
4
|
+
describe Rddd::Service do
|
5
5
|
let(:attributes) { stub('attributes') }
|
6
6
|
|
7
7
|
describe '#initialize' do
|
8
|
-
subject { Service.new(attributes) }
|
8
|
+
subject { Rddd::Service.new(attributes) }
|
9
9
|
|
10
10
|
it 'should store attributes' do
|
11
11
|
subject.instance_variable_get(:@attributes).should == attributes
|
@@ -13,14 +13,14 @@ describe Service do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '#valid?' do
|
16
|
-
subject { Service.new.valid? }
|
16
|
+
subject { Rddd::Service.new.valid? }
|
17
17
|
it { should be_true }
|
18
18
|
end
|
19
19
|
|
20
20
|
describe '#execute' do
|
21
21
|
it 'should raise not implemented' do
|
22
22
|
lambda do
|
23
|
-
Service.new(attributes).execute
|
23
|
+
Rddd::Service.new(attributes).execute
|
24
24
|
end.should raise_exception(NotImplementedError)
|
25
25
|
end
|
26
26
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rddd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -29,6 +29,7 @@ files:
|
|
29
29
|
- lib/rddd.rb
|
30
30
|
- lib/rddd/aggregate_root.rb
|
31
31
|
- lib/rddd/aggregate_root_finders.rb
|
32
|
+
- lib/rddd/configuration.rb
|
32
33
|
- lib/rddd/entity.rb
|
33
34
|
- lib/rddd/repository.rb
|
34
35
|
- lib/rddd/repository_factory.rb
|