euston 1.2.3 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/euston.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'euston'
3
- s.version = '1.2.3'
4
- s.date = '2011-10-24'
3
+ s.version = '1.2.4'
4
+ s.date = '2011-11-29'
5
5
  s.platform = RUBY_PLATFORM.to_s == 'java' ? 'java' : Gem::Platform::RUBY
6
6
  s.authors = ['Lee Henson', 'Guy Boertje']
7
7
  s.email = ['lee.m.henson@gmail.com', 'guyboertje@gmail.com']
@@ -35,6 +35,7 @@ Gem::Specification.new do |s|
35
35
  spec/aggregate_command_map_spec.rb
36
36
  spec/aggregate_root_samples.rb
37
37
  spec/aggregate_root_spec.rb
38
+ spec/command_headers_spec.rb
38
39
  spec/spec_helper.rb
39
40
  ]
40
41
  # = MANIFEST =
@@ -161,10 +161,17 @@ module Euston
161
161
 
162
162
  def deliver_message headers, message, name_method, message_kind, expected_block_kind
163
163
  name = self.class.send(name_method, headers.type, headers.version).to_sym
164
-
165
164
  if respond_to? name
166
165
  @log.debug "Calling #{name} with: #{message.inspect}"
167
- method(name).call OpenStruct.new(message).freeze
166
+ m = method(name)
167
+ case m.arity
168
+ when 2, -2
169
+ m.call OpenStruct.new(headers.to_hash).freeze, OpenStruct.new(message).freeze
170
+ when 1, -1
171
+ m.call OpenStruct.new(message).freeze
172
+ else
173
+ m.call
174
+ end
168
175
  else
169
176
  raise "Couldn't deliver #{message_kind} (#{headers.type} v#{headers.version}) to #{self.class}. Did you forget #{expected_block_kind}?"
170
177
  end
@@ -40,8 +40,7 @@ module Euston
40
40
  private
41
41
 
42
42
  def define_private_method name, &block
43
- block = method(:null_block) if block.nil?
44
- define_method name do |*args| instance_exec *args, &block end
43
+ define_method name, &(block || method(:null_block))
45
44
  end
46
45
 
47
46
  def map_command(entry_point, type, command, opts)
@@ -22,6 +22,14 @@ module Euston
22
22
  @headers[:id] = value
23
23
  end
24
24
 
25
+ def publishing_user_id
26
+ @headers[:user_id]
27
+ end
28
+
29
+ def publishing_user_id= value
30
+ @headers[:user_id] = value
31
+ end
32
+
25
33
  def read_attribute_for_validation key
26
34
  match = /^__(.*)/.match(key.to_s)
27
35
 
@@ -1,29 +1,58 @@
1
1
  module Euston
2
2
  class CommandHeaders
3
- attr_reader :id, :type, :version, :log_completion
4
3
 
5
- def initialize id, type, version, log_completion = false
6
- @id = id
7
- @type = type
8
- @version = version
9
- @log_completion = log_completion
4
+ BASE_KEYS = [:id, :type, :version]
5
+
6
+ def initialize hash
7
+ arg_errors = []
8
+ BASE_KEYS.each do |arg|
9
+ arg_errors << arg unless hash.has_key?(arg)
10
+ end
11
+ raise Errors::CommandHeadersArgumentError.new("Missing args: #{arg_errors.join(", ")}") if arg_errors.size > 0
12
+ @headers = {}.merge(hash)
13
+ @headers[:type] = @headers[:type].to_sym
14
+ @headers_keys = @headers.keys
15
+ end
16
+
17
+ def [] name
18
+ @headers[name.to_sym]
10
19
  end
11
20
 
21
+ # only use method missing for uncommon attributes
22
+ def id() @headers[:id]; end
23
+ def type() @headers[:type]; end
24
+ def version() @headers[:version]; end
25
+
12
26
  def to_hash
13
- {
14
- :id => id,
15
- :type => type,
16
- :version => version,
17
- :log_completion => log_completion
18
- }
27
+ @headers.dup
28
+ end
29
+
30
+ def ==(other)
31
+ @headers == other.to_hash
19
32
  end
20
33
 
21
34
  def self.from_hash hash
22
- self.new hash[:id], hash[:type].to_sym, hash[:version], ( hash[:log_completion] || false )
35
+ self.new hash
23
36
  end
24
37
 
25
38
  def to_s
26
39
  "#{id} #{type} (v#{version})"
27
40
  end
41
+
42
+ def method_missing(name,*args,&block)
43
+ n = name.to_sym
44
+ is_dynamic_method?(n) ? @headers[n] : super
45
+ end
46
+
47
+ # >= 1.9.2
48
+ def respond_to_missing?(name, incl_private)
49
+ is_dynamic_method?(name.to_sym) || super
50
+ end
51
+
52
+ private
53
+
54
+ def is_dynamic_method? name
55
+ (@headers_keys - BASE_KEYS).include?(name)
56
+ end
28
57
  end
29
58
  end
data/lib/euston/errors.rb CHANGED
@@ -2,5 +2,6 @@ module Euston
2
2
  module Errors
3
3
  class InvalidCommandError < StandardError; end
4
4
  class AggregateNotFoundError < StandardError; end
5
+ class CommandHeadersArgumentError < StandardError; end
5
6
  end
6
7
  end
@@ -8,7 +8,7 @@ module Euston
8
8
  end
9
9
 
10
10
  module ClassMethods
11
- def subscribes type, version = 1, opts = nil, &consumer
11
+ def subscribes type, version = 1, opts = {}, &consumer
12
12
  if self.include? Euston::AggregateRoot
13
13
  o = { :id => :id }.merge opts
14
14
 
@@ -21,8 +21,12 @@ module Euston
21
21
  end
22
22
  end
23
23
 
24
- define_method event_handler_method_name(type, version) do |*args|
25
- instance_exec *args, &consumer
24
+ method_name = event_handler_method_name type, version
25
+ define_method method_name, &consumer
26
+ new_method = instance_method method_name
27
+
28
+ define_method method_name do |*args|
29
+ new_method.bind(self).call *args
26
30
  end
27
31
  end
28
32
  end
@@ -1,3 +1,3 @@
1
1
  module Euston
2
- VERSION = "1.2.3"
2
+ VERSION = "1.2.4"
3
3
  end
@@ -6,17 +6,17 @@ module Euston
6
6
  let(:guid1) {Euston.uuid.generate}
7
7
  let(:guid2) {Euston.uuid.generate}
8
8
 
9
- let(:command_cw) { { :headers => CommandHeaders.new(Euston.uuid.generate, :create_widget, 1),
9
+ let(:command_cw) { { :headers => CommandHeaders.new(id: Euston.uuid.generate, type: 'create_widget', version: 1),
10
10
  :body => { :id => guid1} } }
11
- let(:command_iw) { { :headers => CommandHeaders.new(Euston.uuid.generate, :import_widget, 1),
11
+ let(:command_iw) { { :headers => CommandHeaders.new(id: Euston.uuid.generate, type: 'import_widget', version: 1),
12
12
  :body => { :id => guid1, :imported_count => 5 } } }
13
- let(:command_aw) { { :headers => CommandHeaders.new(Euston.uuid.generate, :log_access_to_widget, 1),
13
+ let(:command_aw) { { :headers => CommandHeaders.new(id: Euston.uuid.generate, type: 'log_access_to_widget', version: 1),
14
14
  :body => { :widget_id => guid1 } } }
15
- let(:command_cp) { { :headers => CommandHeaders.new(Euston.uuid.generate, :create_product, 1),
15
+ let(:command_cp) { { :headers => CommandHeaders.new(id: Euston.uuid.generate, type: 'create_product', version: 1),
16
16
  :body => { :id => guid2} } }
17
- let(:command_ip) { { :headers => CommandHeaders.new(Euston.uuid.generate, :import_product, 1),
17
+ let(:command_ip) { { :headers => CommandHeaders.new(id: Euston.uuid.generate, type: 'import_product', version: 1),
18
18
  :body => { :id => guid2, :imported_count => 5 } } }
19
- let(:command_ap) { { :headers => CommandHeaders.new(Euston.uuid.generate, :log_access_to_product, 1),
19
+ let(:command_ap) { { :headers => CommandHeaders.new(id: Euston.uuid.generate, type: 'log_access_to_product', version: 1),
20
20
  :body => { :product_id => guid2 } } }
21
21
 
22
22
  describe "when creating new Aggregates" do
@@ -3,20 +3,20 @@ module Euston
3
3
  class Widget
4
4
  include Euston::AggregateRoot
5
5
 
6
- created_by :create_widget do |command|
6
+ created_by :create_widget do |header, command|
7
7
  apply_event :widget_created, 1, command
8
8
  end
9
9
 
10
- created_by :import_widget do |command|
10
+ created_by :import_widget do |header, command|
11
11
  apply_event :widget_imported, 1, :access_count => (@access_count || 0) + command.imported_count
12
12
  end
13
13
 
14
- consumes :log_access_to_widget, :id => :widget_id do |command|
14
+ consumes :log_access_to_widget, :id => :widget_id do |header, command|
15
15
  apply_event :widget_access_logged, 1, :widget_id => command.widget_id,
16
16
  :access_count => @access_count + 1
17
17
  end
18
18
 
19
- applies :widget_created, 1 do |event|
19
+ applies :widget_created, 1 do
20
20
  @access_count = 0
21
21
  end
22
22
 
@@ -32,11 +32,11 @@ module Euston
32
32
  class Product
33
33
  include Euston::AggregateRoot
34
34
 
35
- created_by :create_product do |command|
35
+ created_by :create_product do |header, command|
36
36
  apply_event :product_created, 1, command
37
37
  end
38
38
 
39
- created_by :import_product do |command|
39
+ created_by :import_product do |header, command|
40
40
  apply_event :product_imported, 1, :access_count => command.imported_count
41
41
  end
42
42
 
@@ -5,7 +5,7 @@ module Euston
5
5
  context 'duplicate command consumption' do
6
6
  let(:aggregate) { Sample::Widget.new }
7
7
  let(:aggregate2) { Sample::Widget.new }
8
- let(:command) { { :headers => CommandHeaders.new(Euston.uuid.generate, :create_widget, 1),
8
+ let(:command) { { :headers => CommandHeaders.new(id: Euston.uuid.generate, type: 'create_widget', version: 1),
9
9
  :body => { :id => Euston.uuid.generate } } }
10
10
 
11
11
  it 'does not handle the same command twice' do
@@ -0,0 +1,51 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ module Euston
4
+ describe 'command_headers' do
5
+ let(:header) { CommandHeaders.new(parameters) }
6
+ context 'a new command headers object' do
7
+ it 'traps incorrect construction' do
8
+ expect { CommandHeaders.new({}) }.to raise_error(Errors::CommandHeadersArgumentError)
9
+ expect { CommandHeaders.new(id: 'foo', type: 'bah') }.to raise_error(Errors::CommandHeadersArgumentError,/version/)
10
+ expect { CommandHeaders.new(type: 'bah', version: 3) }.to raise_error(Errors::CommandHeadersArgumentError,/id/)
11
+ expect { CommandHeaders.new(id: 'foo', version: 2) }.to raise_error(Errors::CommandHeadersArgumentError,/type/)
12
+ end
13
+ let(:parameters) {{ id: 'foo', type: 'bah', version: 3 }}
14
+ it 'creates one from a hash' do
15
+ CommandHeaders.from_hash(parameters).should == header
16
+ end
17
+ end
18
+ context 'accessors' do
19
+ let(:parameters) {{ id: 'foo', type: 'bah', version: 3 }}
20
+ it 'converts type to a symbol' do
21
+ header.type.should == :bah
22
+ end
23
+ it 'has various accessor methods' do
24
+ header.id.should == 'foo'
25
+ header.version.should == 3
26
+ header[:id].should == 'foo'
27
+ header[:type].should == :bah
28
+ header['version'].should == 3
29
+ end
30
+ it 'treats respond_to correctly' do
31
+ header.respond_to?(:type).should be_true
32
+ header.respond_to?(:user_id).should be_false
33
+ end
34
+ end
35
+ context 'with more than the basic attributes' do
36
+ let(:parameters) {{ id: 'foo', type: 'bah', version: 3, user_id: 'bobby123' }}
37
+ it 'allows access to the extra attributes' do
38
+ header.respond_to?(:user_id).should be_true
39
+ header.user_id.should == 'bobby123'
40
+ header[:user_id].should == 'bobby123'
41
+ end
42
+ end
43
+ context 'auxilliary methods' do
44
+ let(:parameters) {{ id: 'foo', type: 'bah', version: 3, user_id: 'bobby123' }}
45
+ it 'has methods' do
46
+ header.to_hash.should == {id: 'foo', type: :bah, version: 3, user_id: 'bobby123'}
47
+ header.to_s.should == 'foo bah (v3)'
48
+ end
49
+ end
50
+ end
51
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,8 @@
1
1
  require 'euston'
2
2
  require 'aggregate_root_samples'
3
+
4
+ def apr(what, header='')
5
+ puts '', "== #{header} =="
6
+ puts what.inspect
7
+ puts ("="*(header.size + 6)), ''
8
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: euston
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3
4
+ version: 1.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-10-24 00:00:00.000000000 Z
13
+ date: 2011-11-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activemodel
17
- requirement: &70270530479600 !ruby/object:Gem::Requirement
17
+ requirement: &70222602188740 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 3.0.10
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70270530479600
25
+ version_requirements: *70222602188740
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: activesupport
28
- requirement: &70270530478760 !ruby/object:Gem::Requirement
28
+ requirement: &70222602187880 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 3.0.10
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70270530478760
36
+ version_requirements: *70222602187880
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: fuubar
39
- requirement: &70270530478060 !ruby/object:Gem::Requirement
39
+ requirement: &70222602187200 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ~>
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: 0.0.0
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *70270530478060
47
+ version_requirements: *70222602187200
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: rspec
50
- requirement: &70270530477300 !ruby/object:Gem::Requirement
50
+ requirement: &70222602186600 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ~>
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: 2.6.0
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *70270530477300
58
+ version_requirements: *70222602186600
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: uuid
61
- requirement: &70270530476640 !ruby/object:Gem::Requirement
61
+ requirement: &70222602186040 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ~>
@@ -66,7 +66,7 @@ dependencies:
66
66
  version: 2.3.0
67
67
  type: :development
68
68
  prerelease: false
69
- version_requirements: *70270530476640
69
+ version_requirements: *70222602186040
70
70
  description: ''
71
71
  email:
72
72
  - lee.m.henson@gmail.com
@@ -99,6 +99,7 @@ files:
99
99
  - spec/aggregate_command_map_spec.rb
100
100
  - spec/aggregate_root_samples.rb
101
101
  - spec/aggregate_root_spec.rb
102
+ - spec/command_headers_spec.rb
102
103
  - spec/spec_helper.rb
103
104
  homepage: http://github.com/leemhenson/euston
104
105
  licenses: []
@@ -128,4 +129,5 @@ test_files:
128
129
  - spec/aggregate_command_map_spec.rb
129
130
  - spec/aggregate_root_samples.rb
130
131
  - spec/aggregate_root_spec.rb
132
+ - spec/command_headers_spec.rb
131
133
  - spec/spec_helper.rb