believer 0.2.5 → 0.2.6
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/README.md +29 -2
- data/lib/believer.rb +5 -0
- data/lib/believer/base.rb +16 -4
- data/lib/believer/column.rb +74 -9
- data/lib/believer/columns.rb +18 -1
- data/lib/believer/command.rb +12 -1
- data/lib/believer/counter.rb +60 -0
- data/lib/believer/counting.rb +29 -0
- data/lib/believer/cql_helper.rb +22 -0
- data/lib/believer/create_table.rb +24 -0
- data/lib/believer/ddl.rb +2 -31
- data/lib/believer/drop_table.rb +9 -0
- data/lib/believer/environment/base_env.rb +5 -0
- data/lib/believer/insert.rb +3 -1
- data/lib/believer/persistence.rb +18 -2
- data/lib/believer/update.rb +52 -0
- data/lib/believer/values.rb +67 -0
- data/lib/believer/version.rb +1 -1
- data/spec/believer/base_spec.rb +9 -2
- data/spec/believer/callback_spec.rb +1 -1
- data/spec/believer/collection_columns_spec.rb +95 -0
- data/spec/believer/columns_spec.rb +21 -0
- data/spec/believer/counter_spec.rb +46 -0
- data/spec/believer/counting_spec.rb +31 -0
- data/spec/believer/delete_spec.rb +1 -1
- data/spec/believer/environment_spec.rb +4 -4
- data/spec/believer/finder_methods_spec.rb +9 -9
- data/spec/believer/insert_spec.rb +1 -1
- data/spec/believer/limit_spec.rb +1 -1
- data/spec/believer/order_by_spec.rb +2 -2
- data/spec/believer/query_spec.rb +2 -2
- data/spec/believer/querying_spec.rb +1 -1
- data/spec/believer/relation_spec.rb +6 -6
- data/spec/believer/test_run_life_cycle_spec.rb +2 -2
- data/spec/believer/time_series_spec.rb +23 -3
- data/spec/believer/update_spec.rb +71 -0
- data/spec/believer/where_spec.rb +4 -4
- data/spec/spec_helper.rb +6 -2
- data/spec/support/setup_database.rb +8 -8
- data/spec/support/test_classes.rb +22 -5
- metadata +17 -19
- data/lib/believer/extensions/will_paginate.rb +0 -173
data/lib/believer/ddl.rb
CHANGED
@@ -6,42 +6,13 @@ module Believer
|
|
6
6
|
module ClassMethods
|
7
7
|
|
8
8
|
def drop_table
|
9
|
-
|
10
|
-
cql = "DROP TABLE #{table_name}"
|
11
|
-
ActiveSupport::Notifications.instrument('ddl.believer', :class => self, :cql => cql, :method => :drop) do
|
12
|
-
connection.execute(cql)
|
13
|
-
end
|
14
|
-
end
|
9
|
+
::Believer::DropTable.new(:record_class => self).execute
|
15
10
|
end
|
16
11
|
|
17
12
|
def create_table
|
18
|
-
|
19
|
-
cql = create_table_cql
|
20
|
-
ActiveSupport::Notifications.instrument('ddl.believer', :class => self, :cql => cql, :method => :create) do
|
21
|
-
connection.execute(cql)
|
22
|
-
end
|
23
|
-
end
|
13
|
+
::Believer::CreateTable.new(:record_class => self).execute
|
24
14
|
end
|
25
15
|
|
26
|
-
def create_table_cql
|
27
|
-
|
28
|
-
keys = []
|
29
|
-
get_primary_key.each do |key_part|
|
30
|
-
if key_part.is_a?(Enumerable)
|
31
|
-
keys << "(#{key_part.join(',')})"
|
32
|
-
else
|
33
|
-
keys << key_part
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
s = "CREATE TABLE #{table_name} (\n"
|
38
|
-
col_statement_parts = columns.keys.map {|col| "#{col} #{columns[col].cql_type}"}
|
39
|
-
s << col_statement_parts.join(",\n")
|
40
|
-
s << ",\n"
|
41
|
-
s << "PRIMARY KEY (#{keys.join(',')})"
|
42
|
-
s << "\n)"
|
43
|
-
s
|
44
|
-
end
|
45
16
|
end
|
46
17
|
|
47
18
|
end
|
@@ -77,6 +77,11 @@ module Believer
|
|
77
77
|
connection
|
78
78
|
end
|
79
79
|
|
80
|
+
def drop_keyspace
|
81
|
+
conn = create_connection(:connect_to_keyspace => false)
|
82
|
+
conn.execute("DROP KEYSPACE #{connection_configuration[:keyspace]}")
|
83
|
+
end
|
84
|
+
|
80
85
|
def create_keyspace(properties = {}, connection = nil)
|
81
86
|
conn = connection || create_connection(:connect_to_keyspace => false)
|
82
87
|
|
data/lib/believer/insert.rb
CHANGED
@@ -11,7 +11,9 @@ module Believer
|
|
11
11
|
|
12
12
|
def to_cql
|
13
13
|
attrs = @values.keys
|
14
|
-
|
14
|
+
cols_def = "#{attrs.join(', ')}"
|
15
|
+
vals_defs = attrs.map { |a| to_cql_literal(@values[a]) }.join(', ')
|
16
|
+
"INSERT INTO #{@record_class.table_name} (#{cols_def}) VALUES (#{vals_defs})"
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
data/lib/believer/persistence.rb
CHANGED
@@ -24,12 +24,28 @@ module Believer
|
|
24
24
|
|
25
25
|
# Saves the model.
|
26
26
|
def save
|
27
|
-
|
27
|
+
if persisted? || is_counter_instance?
|
28
|
+
Update.create(self).execute
|
29
|
+
else
|
30
|
+
Insert.new(:record_class => self.class, :values => self).execute
|
31
|
+
end
|
32
|
+
persisted!
|
33
|
+
self
|
28
34
|
end
|
29
35
|
|
30
36
|
# Destroys the model.
|
31
37
|
def destroy
|
32
|
-
Delete.new(:record_class => self.class).where(key_values).execute
|
38
|
+
res = Delete.new(:record_class => self.class).where(key_values).execute
|
39
|
+
@persisted = false
|
40
|
+
res
|
41
|
+
end
|
42
|
+
|
43
|
+
def persisted!
|
44
|
+
@persisted = true
|
45
|
+
end
|
46
|
+
|
47
|
+
def persisted?
|
48
|
+
@persisted == true
|
33
49
|
end
|
34
50
|
|
35
51
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Believer
|
2
|
+
class Update < FilterCommand
|
3
|
+
include CqlHelper
|
4
|
+
|
5
|
+
attr_accessor :values
|
6
|
+
|
7
|
+
def self.create(object)
|
8
|
+
pk_cols = object.class.primary_key_columns
|
9
|
+
pk_values = object.attributes.delete_if {|k, v| !pk_cols.include?(k)}
|
10
|
+
|
11
|
+
update = new(:record_class => object.class, :values => object.attributes)
|
12
|
+
update.where(pk_values)
|
13
|
+
end
|
14
|
+
|
15
|
+
def query_attributes
|
16
|
+
attrs = super
|
17
|
+
attrs.merge(:values => (values.dup))
|
18
|
+
end
|
19
|
+
|
20
|
+
def values=(v)
|
21
|
+
pk_cols = record_class.primary_key_columns
|
22
|
+
vals = v.is_a?(Base) ? v.attributes : v.to_hash
|
23
|
+
@values = vals.dup.delete_if {|k, v| pk_cols.include?(k)}
|
24
|
+
end
|
25
|
+
|
26
|
+
def can_execute?
|
27
|
+
if record_class.is_counter_table?
|
28
|
+
mock_instance = record_class.new(values)
|
29
|
+
return mock_instance.has_counter_diffs?
|
30
|
+
end
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_cql
|
35
|
+
cql = "UPDATE #{record_class.table_name} SET "
|
36
|
+
cql << values.keys.map {|col| assign_statement(col, values[col]) }.flatten.join(', ')
|
37
|
+
cql << " WHERE #{wheres.map { |wc| "#{wc.to_cql}" }.join(' AND ')}" if wheres.any?
|
38
|
+
cql
|
39
|
+
end
|
40
|
+
|
41
|
+
def assign_statement(col_name, val)
|
42
|
+
column = record_class.columns[col_name]
|
43
|
+
if column.ruby_type == :counter
|
44
|
+
return nil if val.nil?
|
45
|
+
operator = val.incremented? ? '+' : '-'
|
46
|
+
return "#{col_name} = #{col_name} #{operator} #{val.diff}"
|
47
|
+
end
|
48
|
+
"#{col_name} = #{to_cql_literal(val)}"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
data/lib/believer/values.rb
CHANGED
@@ -1,7 +1,28 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module Believer
|
2
4
|
|
3
5
|
module Values
|
4
6
|
|
7
|
+
# Converts the value to a one that conforms to the type of this column
|
8
|
+
# @param v [Object] the value
|
9
|
+
# @param value_type [Symbol] value type
|
10
|
+
def convert_value_to_type(v, value_type)
|
11
|
+
meth = convert_method(value_type)
|
12
|
+
return send(meth, v) if respond_to?(meth)
|
13
|
+
v
|
14
|
+
end
|
15
|
+
|
16
|
+
def convert_method(value_type)
|
17
|
+
return nil if value_type.nil?
|
18
|
+
"convert_to_#{value_type}".to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
def convert_to_string(v)
|
22
|
+
return v.to_s unless v.nil?
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
5
26
|
def convert_to_integer(v)
|
6
27
|
return v.to_i unless v.nil?
|
7
28
|
nil
|
@@ -26,6 +47,52 @@ module Believer
|
|
26
47
|
Time.at(v.to_i)
|
27
48
|
end
|
28
49
|
|
50
|
+
def convert_to_symbol(v)
|
51
|
+
return nil if v.nil?
|
52
|
+
return v.to_sym
|
53
|
+
end
|
54
|
+
|
55
|
+
def convert_to_counter(v)
|
56
|
+
return nil if v.nil?
|
57
|
+
return v if v.is_a?(Counter)
|
58
|
+
Counter.new(v.to_i)
|
59
|
+
end
|
60
|
+
|
61
|
+
def convert_to_array(v, element_type = nil)
|
62
|
+
return nil if v.nil?
|
63
|
+
arr = v.is_a?(Array) ? v : Array.new(v)
|
64
|
+
convert_collection_elements(arr, element_type)
|
65
|
+
end
|
66
|
+
|
67
|
+
def convert_to_set(v, element_type = nil)
|
68
|
+
return nil if v.nil?
|
69
|
+
s = v.is_a?(Set) ? v : Set.new(v)
|
70
|
+
Set.new(convert_collection_elements(s, element_type))
|
71
|
+
end
|
72
|
+
|
73
|
+
def convert_collection_elements(col, element_type = nil)
|
74
|
+
return col if element_type.nil?
|
75
|
+
meth = convert_method(element_type)
|
76
|
+
col.map {|el| send(meth, el)}
|
77
|
+
end
|
78
|
+
|
79
|
+
def convert_to_hash(v, key_type = nil, value_type = nil)
|
80
|
+
return nil if v.nil?
|
81
|
+
hash = v.is_a?(Hash) ? v : Hash.new(v)
|
82
|
+
unless key_type.nil? && value_type.nil?
|
83
|
+
key_conv_meth = convert_method(key_type)
|
84
|
+
val_conv_meth = convert_method(value_type)
|
85
|
+
hash_conv = {}
|
86
|
+
hash.each do |key, value|
|
87
|
+
key_conv = key_conv_meth.nil? ? key : send(key_conv_meth, key)
|
88
|
+
value_conv = val_conv_meth.nil? ? value : send(val_conv_meth, value)
|
89
|
+
hash_conv[key_conv] = value_conv
|
90
|
+
end
|
91
|
+
return hash_conv
|
92
|
+
end
|
93
|
+
hash
|
94
|
+
end
|
95
|
+
|
29
96
|
end
|
30
97
|
|
31
98
|
end
|
data/lib/believer/version.rb
CHANGED
data/spec/believer/base_spec.rb
CHANGED
@@ -2,9 +2,16 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Believer::Base do
|
4
4
|
|
5
|
-
it 'equality' do
|
5
|
+
it 'should implement equality' do
|
6
6
|
a1 = Test::Artist.new(:name => 'Level 42')
|
7
7
|
a2 = Test::Artist.new(:name => 'Level 42', :label => 'Epic')
|
8
|
-
a1.
|
8
|
+
expect(a1).to eql(a2)
|
9
9
|
end
|
10
|
+
|
11
|
+
it 'should be able to reload itself' do
|
12
|
+
artist = Test::Artist.create(:name => 'Level 42', :label => 'Epic')
|
13
|
+
artist.label = 'Apple'
|
14
|
+
expect(artist.reload!.label).to eql('Epic')
|
15
|
+
end
|
16
|
+
|
10
17
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Collection columns' do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@marbles = Set.new [:red, :green, :red]
|
7
|
+
@soccer_cards = ['Messi', 'Ronaldo', 'Pele']
|
8
|
+
@family = {:father => 'Fred', :mother => 'Tina', :sister => 'Emily'}
|
9
|
+
@children = Test::Child.create(:name => 'Johnny', :marbles => @marbles, :family => @family, :soccer_cards => @soccer_cards)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should load a set' do
|
13
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
14
|
+
expect(johnny.marbles.size).to eql(@marbles.size)
|
15
|
+
@marbles.each do |m|
|
16
|
+
expect(johnny.marbles).to include(m)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should be able to add to a set' do
|
21
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
22
|
+
johnny.marbles << :yellow
|
23
|
+
johnny.save
|
24
|
+
|
25
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
26
|
+
expect(johnny.marbles.size).to eql(@marbles.size + 1)
|
27
|
+
expect(johnny.marbles).to include(:yellow)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should be able to remove from a set' do
|
31
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
32
|
+
johnny.marbles.delete(:red)
|
33
|
+
johnny.save
|
34
|
+
|
35
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
36
|
+
expect(johnny.marbles.size).to eql(@marbles.size - 1)
|
37
|
+
expect(johnny.marbles).not_to include(:red)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should load a list' do
|
41
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
42
|
+
expect(johnny.soccer_cards.size).to eql(@soccer_cards.size)
|
43
|
+
@soccer_cards.each do |m|
|
44
|
+
expect(johnny.soccer_cards).to include(m)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should be able to add to a list' do
|
49
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
50
|
+
johnny.soccer_cards << 'Neymar'
|
51
|
+
johnny.save
|
52
|
+
|
53
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
54
|
+
expect(johnny.soccer_cards.size).to eql(@soccer_cards.size + 1)
|
55
|
+
expect(johnny.soccer_cards).to include('Neymar')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should be able to remove from a set' do
|
59
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
60
|
+
johnny.soccer_cards.delete('Messi')
|
61
|
+
johnny.save
|
62
|
+
|
63
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
64
|
+
expect(johnny.soccer_cards.size).to eql(@soccer_cards.size - 1)
|
65
|
+
expect(johnny.soccer_cards).not_to include('Messi')
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should load a map' do
|
69
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
70
|
+
expect(johnny.family.size).to eql(@family.size)
|
71
|
+
@family.each do |k, v|
|
72
|
+
expect(johnny.family.keys).to include(k)
|
73
|
+
expect(johnny.family[k]).to eql(v)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should be able to add to a map' do
|
78
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
79
|
+
johnny.family[:brother] = 'Brad'
|
80
|
+
johnny.save
|
81
|
+
|
82
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
83
|
+
expect(johnny.family[:brother]).to eql('Brad')
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should be able to remove from a map' do
|
87
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
88
|
+
johnny.family.delete(:sister)
|
89
|
+
johnny.save
|
90
|
+
|
91
|
+
johnny = Test::Child.where(:name => 'Johnny').first
|
92
|
+
expect(johnny.family.has_key?(:sister)).to eql(false)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Believer::Columns do
|
4
|
+
|
5
|
+
it 'should be able to find columns with type' do
|
6
|
+
cols = Test::Song.columns
|
7
|
+
expect(cols.size).to eql 5
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should be able to find columns with type' do
|
11
|
+
int_cols = Test::Song.columns_with_type(:integer)
|
12
|
+
expect(int_cols).to eql [Test::Song.columns[:track_number]]
|
13
|
+
|
14
|
+
string_cols = Test::Song.columns_with_type(:string)
|
15
|
+
expect(string_cols.size).to eql 4
|
16
|
+
|
17
|
+
counter_cols = Test::AlbumSales.columns_with_type(:counter)
|
18
|
+
expect(counter_cols).to eql [Test::AlbumSales.columns[:sales]]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Believer::Counter do
|
4
|
+
|
5
|
+
it 'should have a default initial value' do
|
6
|
+
c = Believer::Counter.new(3)
|
7
|
+
expect(c.initial_value).to eql 3
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should increment' do
|
11
|
+
c = Believer::Counter.new(3)
|
12
|
+
c.incr
|
13
|
+
expect(c.initial_value).to eql 3
|
14
|
+
expect(c.to_i).to eql 4
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should decrement' do
|
18
|
+
c = Believer::Counter.new(3)
|
19
|
+
c.decr
|
20
|
+
expect(c.initial_value).to eql 3
|
21
|
+
expect(c.to_i).to eql 2
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should adopt a number value' do
|
25
|
+
c = Believer::Counter.new(3)
|
26
|
+
c.adopt_value(4)
|
27
|
+
expect(c.initial_value).to eql 3
|
28
|
+
expect(c.to_i).to eql 4
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should adopt a counter value' do
|
32
|
+
c = Believer::Counter.new(3)
|
33
|
+
c.adopt_value(Believer::Counter.new(4))
|
34
|
+
expect(c.initial_value).to eql 3
|
35
|
+
expect(c.to_i).to eql 4
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should adopt a nil value' do
|
39
|
+
c = Believer::Counter.new(3)
|
40
|
+
c.adopt_value(nil)
|
41
|
+
expect(c.initial_value).to eql 3
|
42
|
+
expect(c.to_i).to eql 0
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|