believer 0.2.14 → 0.2.15
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.
- data/lib/believer/base.rb +1 -1
- data/lib/believer/counter.rb +6 -0
- data/lib/believer/counting.rb +32 -0
- data/lib/believer/environment/base_env.rb +5 -0
- data/lib/believer/test/database.rb +2 -2
- data/lib/believer/test/test_run_life_cycle.rb +34 -11
- data/lib/believer/version.rb +1 -1
- data/spec/believer/columns_spec.rb +4 -2
- data/spec/believer/counting_spec.rb +40 -26
- data/spec/believer/update_spec.rb +20 -21
- data/spec/support/test_classes.rb +4 -3
- metadata +1 -1
data/lib/believer/base.rb
CHANGED
@@ -23,7 +23,6 @@ module Believer
|
|
23
23
|
attr_accessor :id
|
24
24
|
|
25
25
|
def initialize(attrs = {})
|
26
|
-
@attributes = {}
|
27
26
|
set_attributes(attrs)
|
28
27
|
yield self if block_given?
|
29
28
|
end
|
@@ -47,6 +46,7 @@ module Believer
|
|
47
46
|
end
|
48
47
|
|
49
48
|
def set_attributes(attrs)
|
49
|
+
@attributes = {}
|
50
50
|
attrs.each do |name, val|
|
51
51
|
send("#{name}=".to_sym, val)
|
52
52
|
end if attrs.present?
|
data/lib/believer/counter.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Believer
|
2
2
|
|
3
|
+
# The counter value
|
3
4
|
class Counter
|
4
5
|
|
5
6
|
def initialize(v = 0, initial_val = nil)
|
@@ -7,6 +8,11 @@ module Believer
|
|
7
8
|
@initial_value = initial_val.nil? ? @value : initial_val
|
8
9
|
end
|
9
10
|
|
11
|
+
def reconcile!
|
12
|
+
@initial_value = @value
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
10
16
|
def reset!
|
11
17
|
@value = 0
|
12
18
|
self
|
data/lib/believer/counting.rb
CHANGED
@@ -1,23 +1,29 @@
|
|
1
1
|
module Believer
|
2
|
+
# Model functionality for counter columns
|
2
3
|
module Counting
|
3
4
|
extend ::ActiveSupport::Concern
|
4
5
|
|
5
6
|
module ClassMethods
|
6
7
|
|
8
|
+
# Returns all the counter columns
|
9
|
+
# @return an array of Column
|
7
10
|
def counter_columns
|
8
11
|
columns_with_type(:counter)
|
9
12
|
end
|
10
13
|
|
14
|
+
# Is this a model class with counter columns?
|
11
15
|
def is_counter_table?
|
12
16
|
counter_columns.any?
|
13
17
|
end
|
14
18
|
|
15
19
|
end
|
16
20
|
|
21
|
+
# Is this a model with counters?
|
17
22
|
def is_counter_instance?
|
18
23
|
self.class.is_counter_table?
|
19
24
|
end
|
20
25
|
|
26
|
+
# Returns true if there are any counter increments or decrements
|
21
27
|
def has_counter_diffs?
|
22
28
|
self.class.counter_columns.any? do |col|
|
23
29
|
counter = self.send(col.name)
|
@@ -25,5 +31,31 @@ module Believer
|
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
34
|
+
# Reloads from DB, resets all counters and saves, which effectively resets all counters
|
35
|
+
def reset_counters!
|
36
|
+
reload!
|
37
|
+
self.class.counter_columns.each do |cc|
|
38
|
+
counter = self.send(cc.name)
|
39
|
+
counter.reset! unless counter.nil?
|
40
|
+
end
|
41
|
+
save
|
42
|
+
end
|
43
|
+
|
44
|
+
# Increments a counter and saves the receiver model
|
45
|
+
def incr_counter!(name, val = 1)
|
46
|
+
counter = self.send(name.to_sym)
|
47
|
+
counter.incr(val)
|
48
|
+
save
|
49
|
+
counter.reconcile!
|
50
|
+
end
|
51
|
+
|
52
|
+
# Increments a counter and saves the receiver model
|
53
|
+
def decr_counter!(name, decr = 1)
|
54
|
+
counter = self.send(name.to_sym)
|
55
|
+
counter.decr(val)
|
56
|
+
save
|
57
|
+
counter.reconcile!
|
58
|
+
end
|
59
|
+
|
28
60
|
end
|
29
61
|
end
|
@@ -14,7 +14,7 @@ module Believer
|
|
14
14
|
keyspace = ::Believer::KeySpace.new(env)
|
15
15
|
# First delete the existing keyspace
|
16
16
|
begin
|
17
|
-
|
17
|
+
#env.logger.debug "Dropping keyspace"
|
18
18
|
keyspace.drop
|
19
19
|
rescue Cql::QueryError
|
20
20
|
end
|
@@ -30,7 +30,7 @@ module Believer
|
|
30
30
|
clazz = cl
|
31
31
|
end
|
32
32
|
if clazz.ancestors.include?(Believer::Base)
|
33
|
-
puts "Creating table #{clazz.table_name}"
|
33
|
+
#puts "Creating table #{clazz.table_name}"
|
34
34
|
clazz.create_table()
|
35
35
|
end
|
36
36
|
|
@@ -5,7 +5,7 @@ module Believer
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
|
8
|
+
|
9
9
|
Believer::Base.after_save do |model|
|
10
10
|
Destructor.instance.after_save(model)
|
11
11
|
end
|
@@ -16,21 +16,44 @@ module Believer
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# Detroys all CqlRecord::Base instances created
|
19
|
-
class Destructor
|
19
|
+
class Destructor
|
20
20
|
include Singleton
|
21
|
-
|
21
|
+
|
22
|
+
def counters_action
|
23
|
+
if @counters_action.nil?
|
24
|
+
begin
|
25
|
+
@counters_action = Believer::Base.environment.believer_configuration[:test][:life_cycle][:counters].to_sym
|
26
|
+
rescue
|
27
|
+
@counters_action = :destroy
|
28
|
+
end
|
29
|
+
end
|
30
|
+
@counters_action
|
31
|
+
end
|
32
|
+
|
33
|
+
def should_destroy?(model)
|
34
|
+
#return false if model.is_counter_instance? && retain_counter_models?
|
35
|
+
true
|
36
|
+
end
|
22
37
|
|
23
38
|
def cleanup
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
@observed_models.each do |model|
|
40
|
+
begin
|
41
|
+
if model.is_counter_instance?
|
42
|
+
case counters_action
|
43
|
+
when :destroy
|
44
|
+
model.destroy if should_destroy?(model)
|
45
|
+
when :reset
|
46
|
+
model.reset_counters!
|
47
|
+
when :retain
|
48
|
+
end
|
49
|
+
else
|
50
|
+
model.destroy if should_destroy?(model)
|
30
51
|
end
|
52
|
+
rescue Exception => e
|
53
|
+
puts "Could not destroy model #{model}: #{e}\n#{e.backtrace.join("\n")}"
|
31
54
|
end
|
32
|
-
|
33
|
-
|
55
|
+
end unless @observed_models.nil? || @observed_models.empty?
|
56
|
+
@observed_models = nil
|
34
57
|
end
|
35
58
|
|
36
59
|
def observed_models
|
data/lib/believer/version.rb
CHANGED
@@ -14,8 +14,10 @@ describe Believer::Columns do
|
|
14
14
|
string_cols = Test::Song.columns_with_type(:string)
|
15
15
|
expect(string_cols.size).to eql 4
|
16
16
|
|
17
|
-
counter_cols = Test::
|
18
|
-
expect(counter_cols).to eql
|
17
|
+
counter_cols = Test::AlbumStatistics.columns_with_type(:counter)
|
18
|
+
expect(counter_cols.size).to eql 2
|
19
|
+
expect(counter_cols).to include Test::AlbumStatistics.columns[:sold]
|
20
|
+
expect(counter_cols).to include Test::AlbumStatistics.columns[:produced]
|
19
21
|
end
|
20
22
|
|
21
23
|
end
|
@@ -4,58 +4,72 @@ describe Believer::Counting do
|
|
4
4
|
|
5
5
|
it 'should detect a counter table' do
|
6
6
|
expect(Test::Artist.is_counter_table?).to eql false
|
7
|
-
expect(Test::
|
7
|
+
expect(Test::AlbumStatistics.is_counter_table?).to eql true
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'should detect a changed counter instance' do
|
11
|
-
album_sales = Test::
|
11
|
+
album_sales = Test::AlbumStatistics.new
|
12
12
|
expect(album_sales.has_counter_diffs?).to eql false
|
13
|
-
album_sales.
|
13
|
+
album_sales.sold.incr
|
14
14
|
expect(album_sales.has_counter_diffs?).to eql true
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'should be able to set a counter using a number' do
|
18
|
-
album_sales = Test::
|
19
|
-
album_sales.
|
20
|
-
expect(album_sales.
|
18
|
+
album_sales = Test::AlbumStatistics.new
|
19
|
+
album_sales.sold = 2
|
20
|
+
expect(album_sales.sold.to_i).to eql 2
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'should be able to undo changes in a counter' do
|
24
|
-
album_sales = Test::
|
25
|
-
album_sales.
|
24
|
+
album_sales = Test::AlbumStatistics.new
|
25
|
+
album_sales.sold.incr
|
26
26
|
expect(album_sales.has_counter_diffs?).to eql true
|
27
|
-
album_sales.
|
27
|
+
album_sales.sold.undo_changes!
|
28
28
|
expect(album_sales.has_counter_diffs?).to eql false
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'should be able to reset a counter' do
|
32
32
|
album_attrs = {:artist_name => 'CSNY', :name => 'Deja vu'}
|
33
|
-
album_sales = Test::
|
34
|
-
album_sales.
|
35
|
-
|
33
|
+
album_sales = Test::AlbumStatistics.new(album_attrs)
|
34
|
+
album_sales.incr_counter!(:sold, 4)
|
35
|
+
|
36
|
+
album_sales = Test::AlbumStatistics.where(album_attrs).first
|
37
|
+
expect(album_sales.sold.value).to eql 4
|
38
|
+
album_sales.sold.reset!
|
36
39
|
album_sales.save
|
37
40
|
|
38
|
-
album_sales = Test::
|
39
|
-
expect(album_sales.
|
40
|
-
|
41
|
+
album_sales = Test::AlbumStatistics.where(album_attrs).first
|
42
|
+
expect(album_sales.sold.value).to eql 0
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should be able to reset all counters in one go' do
|
46
|
+
album_attrs = {:artist_name => 'CSNY', :name => 'Deja vu'}
|
47
|
+
album_sales = Test::AlbumStatistics.new(album_attrs)
|
48
|
+
album_sales.sold.incr(4)
|
49
|
+
album_sales.produced.incr(7)
|
50
|
+
expect(album_sales.has_counter_diffs?).to eql true
|
41
51
|
album_sales.save
|
42
52
|
|
43
|
-
album_sales = Test::
|
44
|
-
expect(album_sales.
|
53
|
+
album_sales = Test::AlbumStatistics.where(album_attrs).first
|
54
|
+
expect(album_sales.sold.value).to eql 4
|
55
|
+
expect(album_sales.produced.value).to eql 7
|
56
|
+
album_sales.reset_counters!
|
57
|
+
|
58
|
+
album_sales = Test::AlbumStatistics.where(album_attrs).first
|
59
|
+
expect(album_sales.sold.value).to eql 0
|
60
|
+
expect(album_sales.produced.value).to eql 0
|
45
61
|
end
|
46
62
|
|
47
63
|
it 'should be able to persist a counter value' do
|
48
|
-
album_sales = Test::
|
49
|
-
album_sales.
|
50
|
-
album_sales.
|
51
|
-
expect(album_sales.sales.value).to eql 1
|
64
|
+
album_sales = Test::AlbumStatistics.new(:artist_name => 'CSNY', :name => 'Deja vu')
|
65
|
+
album_sales.incr_counter!(:sold)
|
66
|
+
expect(album_sales.sold.value).to eql 1
|
52
67
|
|
53
|
-
album_sales = Test::
|
54
|
-
album_sales.
|
55
|
-
album_sales.save
|
68
|
+
album_sales = Test::AlbumStatistics.where(:artist_name => 'CSNY', :name => 'Deja vu').first
|
69
|
+
album_sales.incr_counter!(:sold)
|
56
70
|
|
57
|
-
album_sales = Test::
|
58
|
-
expect(album_sales.
|
71
|
+
album_sales = Test::AlbumStatistics.where(:artist_name => 'CSNY', :name => 'Deja vu').first
|
72
|
+
expect(album_sales.sold.value).to eql 2
|
59
73
|
end
|
60
74
|
|
61
75
|
end
|
@@ -6,8 +6,8 @@ describe Believer::Update do
|
|
6
6
|
Test::Artist.create(:name => 'Beatles', :label => 'Apple')
|
7
7
|
end
|
8
8
|
|
9
|
-
let :
|
10
|
-
Test::
|
9
|
+
let :album_statistics do
|
10
|
+
Test::AlbumStatistics.create(:artist_name => 'Beatles', :name => 'Revolver')
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should create statement based on hash" do
|
@@ -21,37 +21,36 @@ describe Believer::Update do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should create create a correct statement for a counter increment" do
|
24
|
-
|
25
|
-
update = Believer::Update.create(
|
26
|
-
expect(update.to_cql).to eql "UPDATE
|
24
|
+
album_statistics.sold.incr(2)
|
25
|
+
update = Believer::Update.create(album_statistics)
|
26
|
+
expect(update.to_cql).to eql "UPDATE album_statistics SET sold = sold + 2 WHERE artist_name = '#{album_statistics.artist_name}' AND name = '#{album_statistics.name}'"
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should create create a correct statement for a counter decrement" do
|
30
|
-
|
31
|
-
update = Believer::Update.create(
|
32
|
-
expect(update.to_cql).to eql "UPDATE
|
30
|
+
album_statistics.sold.decr(2)
|
31
|
+
update = Believer::Update.create(album_statistics)
|
32
|
+
expect(update.to_cql).to eql "UPDATE album_statistics SET sold = sold - 2 WHERE artist_name = '#{album_statistics.artist_name}' AND name = '#{album_statistics.name}'"
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should execute a counter change" do
|
36
|
-
cur_val =
|
37
|
-
|
38
|
-
update = Believer::Update.create(
|
36
|
+
cur_val = album_statistics.sold.to_i
|
37
|
+
album_statistics.sold.incr(2)
|
38
|
+
update = Believer::Update.create(album_statistics)
|
39
39
|
update.execute
|
40
|
-
|
41
|
-
expect(
|
40
|
+
cur_album_statistics = Test::AlbumStatistics.where(album_statistics.key_values).first
|
41
|
+
expect(cur_album_statistics.sold.to_i).to eql (cur_val + 2)
|
42
42
|
end
|
43
43
|
|
44
44
|
it "should not execute if no changes are detected in any counter" do
|
45
|
-
cur_val =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
update = Believer::Update.create(album_sales)
|
45
|
+
cur_val = album_statistics.reload!.sold.to_i
|
46
|
+
album_statistics.sold.incr(2)
|
47
|
+
album_statistics.sold.decr(2)
|
48
|
+
expect(album_statistics.sold.to_i).to eql cur_val
|
49
|
+
update = Believer::Update.create(album_statistics)
|
51
50
|
expect(update.execute).to eql false
|
52
51
|
|
53
|
-
|
54
|
-
expect(
|
52
|
+
cur_album_statistics = Test::AlbumStatistics.where(album_statistics.key_values).first
|
53
|
+
expect(cur_album_statistics.sold.to_i).to eql cur_val
|
55
54
|
end
|
56
55
|
|
57
56
|
it "should update the values" do
|
@@ -34,11 +34,12 @@ module Test
|
|
34
34
|
has_single :album, :class => 'Test::Album', :key => [:artist_name, :album_name], :foreign_key => [:artist_name, :name]
|
35
35
|
end
|
36
36
|
|
37
|
-
class
|
37
|
+
class AlbumStatistics < Believer::Base
|
38
38
|
column :artist_name
|
39
39
|
column :name
|
40
40
|
|
41
|
-
column :
|
41
|
+
column :sold, :type => :counter
|
42
|
+
column :produced, :type => :counter
|
42
43
|
|
43
44
|
primary_key :artist_name, :name
|
44
45
|
end
|
@@ -93,7 +94,7 @@ module Test
|
|
93
94
|
end
|
94
95
|
|
95
96
|
Believer::Base.environment = test_environment
|
96
|
-
CLASSES = [Artist, Album, Song,
|
97
|
+
CLASSES = [Artist, Album, Song, AlbumStatistics, Event, Person, Child]
|
97
98
|
#CLASSES.each {|cl| cl.environment = test_environment}
|
98
99
|
|
99
100
|
def self.classes
|