believer 0.2.5 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|