entity_store 0.0.2 → 0.0.3

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.
@@ -1,13 +1,13 @@
1
1
  module EntityStore
2
2
  module Event
3
- attr_accessor :entity_id
4
-
3
+ attr_accessor :entity_id, :entity_version
4
+
5
5
  def initialize(attrs={})
6
- attrs.each_pair do |key, value|
6
+ attrs.each_pair do |key, value|
7
7
  send("#{key}=", value) if respond_to?("#{key}=")
8
8
  end
9
9
  end
10
-
10
+
11
11
  def receiver_name
12
12
  elements = self.class.name.split('::')
13
13
  elements[elements.count - 1].
@@ -16,20 +16,20 @@ module EntityStore
16
16
  tr("-", "_").
17
17
  downcase
18
18
  end
19
-
19
+
20
20
  def attributes
21
21
  Hash[*public_methods.select {|m| m =~ /\w\=$/}.collect do |m|
22
22
  attribute_name = m.to_s.chop.to_sym
23
23
  [attribute_name, send(attribute_name).respond_to?(:attributes) ? send(attribute_name).attributes : send(attribute_name)]
24
24
  end.flatten]
25
25
  end
26
-
26
+
27
27
  def self.included(klass)
28
28
  klass.class_eval do
29
29
  extend ClassMethods
30
30
  end
31
31
  end
32
-
32
+
33
33
  module ClassMethods
34
34
  def time_attribute(*names)
35
35
  class_eval do
@@ -44,7 +44,7 @@ module EntityStore
44
44
  end
45
45
  end
46
46
  end
47
-
47
+
48
48
  def entity_value_attribute(name, klass)
49
49
  define_method(name) { instance_variable_get("@#{name}") }
50
50
  define_method("#{name}=") do |value|
@@ -3,7 +3,9 @@ module EntityStore
3
3
  class << self
4
4
  def publish(entity_type, event)
5
5
  publish_externally entity_type, event
6
-
6
+
7
+ EntityStore.logger.debug { "publishing #{event.inspect}" }
8
+
7
9
  subscribers_to(event.receiver_name).each do |s|
8
10
  begin
9
11
  s.new.send(event.receiver_name, event)
@@ -17,15 +19,15 @@ module EntityStore
17
19
  def subscribers_to(event_name)
18
20
  subscribers.select { |s| s.instance_methods.include?(event_name.to_sym) }
19
21
  end
20
-
22
+
21
23
  def subscribers
22
24
  EntityStore.event_subscribers
23
25
  end
24
-
26
+
25
27
  def publish_externally(entity_type, event)
26
28
  external_store.add_event(entity_type, event)
27
29
  end
28
-
30
+
29
31
  def external_store
30
32
  @_external_store ||= ExternalStore.new
31
33
  end
@@ -3,16 +3,16 @@ module EntityStore
3
3
  def storage_client
4
4
  @storage_client || MongoEntityStore.new
5
5
  end
6
-
7
- def add(entity)
8
- entity.id = storage_client.add_entity(entity)
6
+
7
+ def add(entity)
8
+ entity.id = storage_client.add_entity(entity)
9
9
  add_events(entity)
10
10
  return entity
11
11
  rescue => e
12
12
  EntityStore.logger.error { "Store#add error: #{e.inspect} - #{entity.inspect}" }
13
13
  raise e
14
14
  end
15
-
15
+
16
16
  def save(entity)
17
17
  # need to look at concurrency if we start storing version on client
18
18
  entity.version += 1
@@ -23,10 +23,11 @@ module EntityStore
23
23
  EntityStore.logger.error { "Store#save error: #{e.inspect} - #{entity.inspect}" }
24
24
  raise e
25
25
  end
26
-
26
+
27
27
  def add_events(entity)
28
28
  entity.pending_events.each do |e|
29
29
  e.entity_id = entity.id.to_s
30
+ e.entity_version = entity.version
30
31
  storage_client.add_event(e)
31
32
  end
32
33
  entity.pending_events.each {|e| EventBus.publish(entity.type, e) }
@@ -35,22 +36,22 @@ module EntityStore
35
36
  def get!(id)
36
37
  get(id, true)
37
38
  end
38
-
39
+
39
40
  def get(id, raise_exception=false)
40
41
  if entity = storage_client.get_entity(id, raise_exception)
41
- storage_client.get_events(id).each { |e| e.apply(entity) }
42
- end
42
+ storage_client.get_events(id).each { |e| e.apply(entity) }
43
+ end
43
44
  return entity
44
45
  end
45
-
46
+
46
47
  # Public : USE AT YOUR PERIL this clears the ENTIRE data store
47
- #
48
+ #
48
49
  # Returns nothing
49
50
  def clear_all
50
51
  storage_client.entities.drop
51
52
  storage_client.events.drop
52
53
  @storage_client = nil
53
54
  end
54
-
55
+
55
56
  end
56
57
  end
@@ -1,3 +1,3 @@
1
1
  module EntityStore
2
- VERSION = "0.0.2".freeze
2
+ VERSION = "0.0.3".freeze
3
3
  end
@@ -16,18 +16,22 @@ end
16
16
  describe Event do
17
17
  before(:each) do
18
18
  @id = random_integer
19
+ @version = random_integer
19
20
  @name = random_string
20
21
  @time = random_time
21
22
  @town = random_string
22
23
  @county = random_string
23
24
  end
24
25
  describe "#initialize" do
25
-
26
- subject { DummyEvent.new({:entity_id => @id, :name => @name, :updated_at => @time, :sent_at => nil, :address => {:town => @town, :county => @county}})}
27
-
26
+
27
+ subject { DummyEvent.new({:entity_id => @id, :entity_version => @version, :name => @name, :updated_at => @time, :sent_at => nil, :address => {:town => @town, :county => @county}})}
28
+
28
29
  it "should set entity_id" do
29
30
  subject.entity_id.should eq(@id)
30
31
  end
32
+ it "should set entity_version" do
33
+ subject.entity_version.should eq(@version)
34
+ end
31
35
  it "should set name" do
32
36
  subject.name.should eq(@name)
33
37
  end
@@ -41,27 +45,27 @@ describe Event do
41
45
  subject.address.county.should eq(@county)
42
46
  end
43
47
  end
44
-
48
+
45
49
  describe "#attributes" do
46
50
  before(:each) do
47
- @event = DummyEvent.new(:entity_id => @id, :name => @name, :updated_at => @time, :address => DummyValue.new(:town => @town, :county => @county))
51
+ @event = DummyEvent.new(:entity_id => @id, :entity_version => @version, :name => @name, :updated_at => @time, :address => DummyValue.new(:town => @town, :county => @county))
48
52
  end
49
-
53
+
50
54
  subject { @event.attributes }
51
-
55
+
52
56
  it "returns a hash of the attributes" do
53
- subject.should eq({:entity_id => @id, :name => @name, :updated_at => @time, :sent_at => nil, :address => {:town => @town, :county => @county}})
57
+ subject.should eq({:entity_id => @id, :entity_version => @version, :name => @name, :updated_at => @time, :sent_at => nil, :address => {:town => @town, :county => @county}})
54
58
  end
55
59
  end
56
-
60
+
57
61
  describe ".time_attribute" do
58
62
  before(:each) do
59
63
  @event = DummyEvent.new
60
64
  @time = random_time
61
65
  end
62
- context "updated_at" do
66
+ context "updated_at" do
63
67
  subject { @event.updated_at = @time.to_s }
64
-
68
+
65
69
  it "parses the time field when added as a string" do
66
70
  subject
67
71
  @event.updated_at.to_i.should eq(@time.to_i)
@@ -69,14 +73,14 @@ describe Event do
69
73
  end
70
74
  context "sent_at" do
71
75
  subject { @event.updated_at = @time.to_s }
72
-
76
+
73
77
  it "parses the time field when added as a string" do
74
78
  subject
75
79
  @event.updated_at.to_i.should eq(@time.to_i)
76
80
  end
77
81
  end
78
82
  end
79
-
83
+
80
84
  describe ".value_attribute" do
81
85
  before(:each) do
82
86
  @event = DummyEvent.new
@@ -2,9 +2,9 @@ require 'spec_helper'
2
2
 
3
3
  class DummyEntity
4
4
  include Entity
5
-
5
+
6
6
  attr_accessor :name
7
-
7
+
8
8
  def initialize(name)
9
9
  @name = name
10
10
  end
@@ -20,9 +20,9 @@ describe Store do
20
20
  @store.stub(:add_events)
21
21
  @store.stub(:storage_client) { @storage_client }
22
22
  end
23
-
23
+
24
24
  subject { @store.add(@entity) }
25
-
25
+
26
26
  it "adds the new entity to the store" do
27
27
  @storage_client.should_receive(:add_entity).with(@entity)
28
28
  subject
@@ -33,23 +33,24 @@ describe Store do
33
33
  end
34
34
  it "returns a reference to the ride" do
35
35
  subject.should eq(@entity)
36
- end
36
+ end
37
37
  end
38
38
 
39
39
  describe "#add_events" do
40
40
  before(:each) do
41
41
  @entity = DummyEntity.new(random_string)
42
42
  @entity.id = random_string
43
- @entity.pending_events << mock(Event, :entity_id= => true)
44
- @entity.pending_events << mock(Event, :entity_id= => true)
43
+ @entity.version = random_integer
44
+ @entity.pending_events << mock(Event, :entity_id= => true, :entity_version= => true)
45
+ @entity.pending_events << mock(Event, :entity_id= => true, :entity_version= => true)
45
46
  @storage_client = mock("StorageClient", :add_event => true)
46
47
  @store = Store.new
47
48
  @store.stub(:storage_client) { @storage_client }
48
49
  EventBus.stub(:publish)
49
50
  end
50
-
51
+
51
52
  subject { @store.add_events(@entity) }
52
-
53
+
53
54
  it "adds each of the events" do
54
55
  @entity.pending_events.each do |e|
55
56
  @storage_client.should_receive(:add_event).with(e)
@@ -62,15 +63,21 @@ describe Store do
62
63
  end
63
64
  subject
64
65
  end
66
+ it "should assign the current entity version to each event" do
67
+ @entity.pending_events.each do |e|
68
+ e.should_receive(:entity_version=).with(@entity.version)
69
+ end
70
+ subject
71
+ end
65
72
  it "publishes each event to the EventBus" do
66
73
  @entity.pending_events.each do |e|
67
74
  EventBus.should_receive(:publish).with(@entity.type, e)
68
75
  end
69
76
  subject
70
77
  end
71
-
78
+
72
79
  end
73
-
80
+
74
81
  describe "#save" do
75
82
  before(:each) do
76
83
  @new_id = random_string
@@ -80,9 +87,9 @@ describe Store do
80
87
  @store.stub(:add_events)
81
88
  @store.stub(:storage_client) { @storage_client }
82
89
  end
83
-
90
+
84
91
  subject { @store.save(@entity) }
85
-
92
+
86
93
  it "increments the entity version number" do
87
94
  @entity.should_receive(:version=).with(@entity.version + 1)
88
95
  subject
@@ -99,21 +106,21 @@ describe Store do
99
106
  subject.should eq(@entity)
100
107
  end
101
108
  end
102
-
109
+
103
110
  describe "#get" do
104
111
  before(:each) do
105
112
  @id = random_integer
106
113
  @entity = DummyEntity.new(random_string)
107
114
  DummyEntity.stub(:new).and_return(@ride)
108
115
  @events = [mock("Event", :apply => true), mock("Event", :apply => true)]
109
-
116
+
110
117
  @storage_client = mock("StorageClient", :get_entity => @entity, :get_events => @events)
111
118
  @store = Store.new
112
119
  @store.stub(:storage_client) { @storage_client }
113
120
  end
114
-
121
+
115
122
  subject { @store.get(@id) }
116
-
123
+
117
124
  it "should retrieve object from the storage client" do
118
125
  @storage_client.should_receive(:get_entity).with(@id, false)
119
126
  subject
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entity_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-30 00:00:00.000000000 Z
12
+ date: 2012-07-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongo
16
- requirement: &70160207835100 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '1.6'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70160207835100
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.6'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: bson_ext
27
- requirement: &70160207834240 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,7 +37,12 @@ dependencies:
32
37
  version: '1.6'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70160207834240
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.6'
36
46
  description: Event sourced entity store with a Mongo body
37
47
  email: adam.bird@gmail.com
38
48
  executables: []
@@ -80,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
90
  version: '0'
81
91
  requirements: []
82
92
  rubyforge_project:
83
- rubygems_version: 1.8.10
93
+ rubygems_version: 1.8.24
84
94
  signing_key:
85
95
  specification_version: 3
86
96
  summary: Event sourced entity store with a Mongo body