extendi-cassandra_object 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.travis.yml +23 -0
  4. data/CHANGELOG +0 -0
  5. data/Gemfile +17 -0
  6. data/LICENSE +13 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +177 -0
  9. data/Rakefile +12 -0
  10. data/extendi-cassandra_object.gemspec +26 -0
  11. data/lib/cassandra_object.rb +73 -0
  12. data/lib/cassandra_object/adapters/abstract_adapter.rb +61 -0
  13. data/lib/cassandra_object/adapters/cassandra_adapter.rb +269 -0
  14. data/lib/cassandra_object/adapters/cassandra_schemaless_adapter.rb +306 -0
  15. data/lib/cassandra_object/attribute_methods.rb +96 -0
  16. data/lib/cassandra_object/attribute_methods/definition.rb +22 -0
  17. data/lib/cassandra_object/attribute_methods/dirty.rb +36 -0
  18. data/lib/cassandra_object/attribute_methods/primary_key.rb +25 -0
  19. data/lib/cassandra_object/attribute_methods/typecasting.rb +59 -0
  20. data/lib/cassandra_object/base.rb +33 -0
  21. data/lib/cassandra_object/base_schema.rb +11 -0
  22. data/lib/cassandra_object/base_schemaless.rb +11 -0
  23. data/lib/cassandra_object/base_schemaless_dynamic.rb +11 -0
  24. data/lib/cassandra_object/belongs_to.rb +63 -0
  25. data/lib/cassandra_object/belongs_to/association.rb +49 -0
  26. data/lib/cassandra_object/belongs_to/builder.rb +40 -0
  27. data/lib/cassandra_object/belongs_to/reflection.rb +30 -0
  28. data/lib/cassandra_object/callbacks.rb +29 -0
  29. data/lib/cassandra_object/core.rb +63 -0
  30. data/lib/cassandra_object/errors.rb +10 -0
  31. data/lib/cassandra_object/identity.rb +26 -0
  32. data/lib/cassandra_object/inspect.rb +25 -0
  33. data/lib/cassandra_object/log_subscriber.rb +44 -0
  34. data/lib/cassandra_object/model.rb +60 -0
  35. data/lib/cassandra_object/persistence.rb +203 -0
  36. data/lib/cassandra_object/railtie.rb +33 -0
  37. data/lib/cassandra_object/railties/controller_runtime.rb +45 -0
  38. data/lib/cassandra_object/schema.rb +83 -0
  39. data/lib/cassandra_object/schemaless.rb +83 -0
  40. data/lib/cassandra_object/scope.rb +86 -0
  41. data/lib/cassandra_object/scope/finder_methods.rb +54 -0
  42. data/lib/cassandra_object/scope/query_methods.rb +69 -0
  43. data/lib/cassandra_object/scoping.rb +27 -0
  44. data/lib/cassandra_object/serialization.rb +6 -0
  45. data/lib/cassandra_object/tasks/ks.rake +54 -0
  46. data/lib/cassandra_object/timestamps.rb +19 -0
  47. data/lib/cassandra_object/type.rb +16 -0
  48. data/lib/cassandra_object/types.rb +8 -0
  49. data/lib/cassandra_object/types/array_type.rb +16 -0
  50. data/lib/cassandra_object/types/base_type.rb +26 -0
  51. data/lib/cassandra_object/types/boolean_type.rb +20 -0
  52. data/lib/cassandra_object/types/date_type.rb +22 -0
  53. data/lib/cassandra_object/types/float_type.rb +16 -0
  54. data/lib/cassandra_object/types/integer_type.rb +20 -0
  55. data/lib/cassandra_object/types/json_type.rb +13 -0
  56. data/lib/cassandra_object/types/string_type.rb +19 -0
  57. data/lib/cassandra_object/types/time_type.rb +16 -0
  58. data/lib/cassandra_object/types/type_helper.rb +39 -0
  59. data/lib/cassandra_object/validations.rb +44 -0
  60. data/test/support/cassandra.rb +63 -0
  61. data/test/support/issue.rb +12 -0
  62. data/test/support/issue_dynamic.rb +12 -0
  63. data/test/support/issue_schema.rb +17 -0
  64. data/test/support/issue_schema_child.rb +17 -0
  65. data/test/support/issue_schema_father.rb +13 -0
  66. data/test/test_helper.rb +41 -0
  67. data/test/unit/active_model_test.rb +18 -0
  68. data/test/unit/adapters/adapter_test.rb +6 -0
  69. data/test/unit/attribute_methods/definition_test.rb +13 -0
  70. data/test/unit/attribute_methods/dirty_test.rb +72 -0
  71. data/test/unit/attribute_methods/primary_key_test.rb +26 -0
  72. data/test/unit/attribute_methods/typecasting_test.rb +119 -0
  73. data/test/unit/attribute_methods_test.rb +51 -0
  74. data/test/unit/base_test.rb +20 -0
  75. data/test/unit/belongs_to/reflection_test.rb +12 -0
  76. data/test/unit/belongs_to_test.rb +63 -0
  77. data/test/unit/callbacks_test.rb +46 -0
  78. data/test/unit/connection_test.rb +6 -0
  79. data/test/unit/connections/connections_test.rb +55 -0
  80. data/test/unit/core_test.rb +55 -0
  81. data/test/unit/identity_test.rb +26 -0
  82. data/test/unit/inspect_test.rb +26 -0
  83. data/test/unit/log_subscriber_test.rb +25 -0
  84. data/test/unit/persistence_schema_test.rb +156 -0
  85. data/test/unit/persistence_test.rb +266 -0
  86. data/test/unit/railties/controller_runtime_test.rb +48 -0
  87. data/test/unit/schema/tasks_test.rb +32 -0
  88. data/test/unit/schema_test.rb +115 -0
  89. data/test/unit/schemaless_test.rb +100 -0
  90. data/test/unit/scope/finder_methods_test.rb +117 -0
  91. data/test/unit/scope/query_methods_test.rb +32 -0
  92. data/test/unit/scoping_test.rb +7 -0
  93. data/test/unit/timestamps_test.rb +27 -0
  94. data/test/unit/types/array_type_test.rb +17 -0
  95. data/test/unit/types/base_type_test.rb +19 -0
  96. data/test/unit/types/boolean_type_test.rb +24 -0
  97. data/test/unit/types/date_type_test.rb +15 -0
  98. data/test/unit/types/float_type_test.rb +17 -0
  99. data/test/unit/types/integer_type_test.rb +19 -0
  100. data/test/unit/types/json_type_test.rb +23 -0
  101. data/test/unit/types/string_type_test.rb +25 -0
  102. data/test/unit/types/time_type_test.rb +14 -0
  103. data/test/unit/validations_test.rb +27 -0
  104. metadata +202 -0
@@ -0,0 +1,100 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::SchemalessTest < CassandraObject::TestCase
4
+
5
+ test 'create_keyspace' do
6
+ CassandraObject::Schemaless.create_keyspace 'Blah'
7
+ begin
8
+ existing_keyspace = false
9
+ CassandraObject::Schemaless.create_keyspace 'Blah'
10
+ rescue Exception => e
11
+ assert_equal e.message, 'Cannot add existing keyspace "blah"'
12
+ existing_keyspace = true
13
+ ensure
14
+ CassandraObject::Schemaless.drop_keyspace 'Blah'
15
+ end
16
+
17
+ assert existing_keyspace
18
+ end
19
+
20
+ test 'drop undroppable' do
21
+ begin
22
+ CassandraObject::Schemaless.drop_keyspace 'cassandra_object_test'
23
+ rescue Exception => e
24
+ assert_equal e.message, 'Cannot drop keyspace cassandra_object_test. You must delete all tables before'
25
+ ensure
26
+ end
27
+ end
28
+
29
+ test 'create_table' do
30
+
31
+ CassandraObject::Schemaless.create_table 'TestRecords'
32
+
33
+ begin
34
+ CassandraObject::Schemaless.create_table 'TestRecords'
35
+ assert false, 'TestRecords should already exist'
36
+ rescue Exception => e
37
+ assert_equal e.message.gsub('column family', 'table'), 'Cannot add already existing table "testrecords" to keyspace "cassandra_object_test"'
38
+ end
39
+ end
40
+
41
+ test 'drop_table' do
42
+ class TestDrop < CassandraObject::BaseSchemaless
43
+ self.column_family = 'TestCFToDrop1'
44
+ end
45
+
46
+ CassandraObject::Schemaless.create_table 'TestCFToDrop1'
47
+ TestDrop.create
48
+ begin
49
+ CassandraObject::Schemaless.drop_table 'TestCFToDrop1'
50
+ rescue Exception => e
51
+ assert_equal e.message, 'The table TestCFToDrop1 is not empty! If you want to drop it add the option confirm = true'
52
+ end
53
+ end
54
+
55
+ test 'drop with confirm' do
56
+ CassandraObject::Schemaless.create_table 'TestCFToDrop2'
57
+
58
+ CassandraObject::Schemaless.drop_table 'TestCFToDrop2', true
59
+ begin
60
+ CassandraObject::Schemaless.drop_table 'TestCFToDrop2'
61
+ assert false, 'TestCFToDrop2 should not exist'
62
+ rescue Exception => e
63
+ assert_equal e.message.gsub('columnfamily', 'table'), 'unconfigured table testcftodrop2'
64
+ end
65
+ end
66
+
67
+ test 'drop empty' do
68
+ CassandraObject::Schemaless.create_table 'TestCFToDrop3'
69
+
70
+ CassandraObject::Schemaless.drop_table 'TestCFToDrop3'
71
+ begin
72
+ CassandraObject::Schemaless.drop_table 'TestCFToDrop3'
73
+ assert false, 'TestCFToDrop3 should not exist'
74
+ rescue Exception => e
75
+ assert_equal e.message.gsub('columnfamily', 'table'), 'unconfigured table testcftodrop3'
76
+ end
77
+ end
78
+
79
+ test 'create_index' do
80
+ CassandraObject::Schemaless.create_column_family 'TestIndexed'
81
+
82
+ CassandraObject::Schemaless.alter_column_family 'TestIndexed', 'ADD id_value varchar'
83
+
84
+ CassandraObject::Schemaless.add_index 'TestIndexed', 'id_value'
85
+ end
86
+
87
+ test 'drop_index' do
88
+ CassandraObject::Schemaless.create_column_family 'TestDropIndexes'
89
+
90
+ CassandraObject::Schemaless.alter_column_family 'TestDropIndexes', 'ADD id_value1 varchar'
91
+ CassandraObject::Schemaless.alter_column_family 'TestDropIndexes', 'ADD id_value2 varchar'
92
+
93
+ CassandraObject::Schemaless.add_index 'TestDropIndexes', 'id_value1'
94
+ CassandraObject::Schemaless.add_index 'TestDropIndexes', 'id_value2', 'special_name'
95
+
96
+ CassandraObject::Schemaless.drop_index 'TestDropIndexes_id_value1_idx'
97
+ CassandraObject::Schemaless.drop_index 'special_name'
98
+ end
99
+
100
+ end
@@ -0,0 +1,117 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::FinderMethodsTest < CassandraObject::TestCase
4
+ test 'find' do
5
+ Issue.create.tap do |issue|
6
+ assert_equal issue, Issue.find(issue.id)
7
+ end
8
+
9
+ begin
10
+ Issue.find(nil)
11
+ assert false
12
+ rescue => e
13
+ assert_equal "Couldn't find Issue with key nil", e.message
14
+ end
15
+
16
+ assert_raise CassandraObject::RecordNotFound do
17
+ Issue.find('what')
18
+ end
19
+ end
20
+
21
+ test 'find with ids' do
22
+ first_issue = Issue.create
23
+ second_issue = Issue.create
24
+
25
+ assert_equal [], Issue.find([])
26
+ assert_equal [first_issue, second_issue].to_set, Issue.find([first_issue.id, second_issue.id]).to_set
27
+ end
28
+
29
+ test 'find_by_id' do
30
+ Issue.create.tap do |issue|
31
+ assert_equal issue, Issue.find_by_id(issue.id)
32
+ end
33
+
34
+ assert_nil Issue.find_by_id('what')
35
+ end
36
+
37
+ test 'find all in batches dynamic' do
38
+ first_issue = IssueDynamic.create(key: '1', title: 'tit', dynamic_field1: 'one', dynamic_field2: 'two')
39
+ second_issue = IssueDynamic.create(key: '2', title: 'tit', dynamic_field1: 'one', dynamic_field2: 'two')
40
+ res = IssueDynamic.find_all_in_batches
41
+ reobjected = res[:results].map { |key, val| {key: key }.merge(val) }
42
+
43
+ assert_equal [first_issue, second_issue].size, reobjected.size
44
+ end
45
+
46
+ test 'find all in batches dynamic paged' do
47
+
48
+ issues = []
49
+ 100.times.each do |i|
50
+ issues << IssueDynamic.create(key: i, title: 'tit', dynamic_field1: 'one', dynamic_field2: 'two')
51
+ end
52
+
53
+ res = []
54
+ next_cursor = nil
55
+ iter = 0
56
+ loop do
57
+ iter += 1
58
+ resp = IssueDynamic.limit(10).find_all_in_batches(next_cursor)
59
+ res << resp[:results].map { |key, val| {key: key.to_s }.merge(val) }
60
+ next_cursor = resp[:next_cursor]
61
+ break if next_cursor.nil?
62
+ end
63
+ res.flatten!
64
+ IssueDynamic.delete(issues.map{|x| x[:key]})
65
+
66
+ assert_equal issues.size, res.size
67
+ end
68
+
69
+ test 'first' do
70
+ first_issue = Issue.create
71
+ second_issue = Issue.create
72
+
73
+ assert [first_issue, second_issue].include?(Issue.first)
74
+ end
75
+
76
+ test 'cql response: find with ids' do
77
+ first_issue = Issue.create
78
+ second_issue = Issue.create
79
+
80
+ assert_equal [], Issue.find([])
81
+ assert_equal [first_issue.get_cql_response, second_issue.get_cql_response].to_set, Issue.cql_response.find([first_issue.id, second_issue.id]).to_set
82
+ end
83
+
84
+ test 'cql response: find_by_id' do
85
+ Issue.create.tap do |issue|
86
+ assert_equal issue.get_cql_response, Issue.cql_response.find_by_id(issue.id)
87
+ end
88
+
89
+ assert_nil Issue.find_by_id('what')
90
+ end
91
+
92
+ # test 'cql response: all' do
93
+ # first_issue = Issue.create
94
+ # second_issue = Issue.create
95
+ # assert_equal [first_issue.get_cql_response, second_issue.get_cql_response].to_set, Issue.cql_response.find_all_in_batches[:results].to_set
96
+ # end
97
+
98
+ test 'cql response: first' do
99
+ first_issue = Issue.create
100
+ second_issue = Issue.create
101
+ assert [first_issue.id, second_issue.id].include?(Issue.cql_response.first.keys.first)
102
+ end
103
+
104
+ test 'where' do
105
+ # todo make better tests
106
+ # mono parameter
107
+ res1 = Issue.cql_response.where("column1 < 'poi'").to_a
108
+ # bi parameter
109
+ res = Issue.cql_response.where('column1 < ?', 'poi').to_a
110
+ end
111
+
112
+ # test 'limit in first' do
113
+ # first_issue = IssueDynamic.create(key: '1', title: 'tit', dynamic_field1: 'one', dynamic_field2: 'two')
114
+ # f = IssueDynamic.first
115
+ # end
116
+
117
+ end
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Scope::QueryMethodsTest < CassandraObject::TestCase
4
+ test 'select' do
5
+ original_issue = Issue.create title: 'foo', description: 'bar'
6
+ found_issue = Issue.select(:title).find(original_issue.id)
7
+
8
+ assert_equal 'foo', found_issue.title
9
+ assert_equal original_issue.id, found_issue.id
10
+ assert_nil found_issue.description
11
+ end
12
+
13
+ test 'select with block' do
14
+ foo_issue = Issue.create title: 'foo'
15
+ Issue.create title: 'bar'
16
+ assert_equal [foo_issue], Issue.find_all_in_batches[:results].select { |issue| issue.title == 'foo' }
17
+ end
18
+
19
+ test 'chaining where with scope' do
20
+ issue = Issue.create title: 'abc', description: 'def'
21
+ query = Issue.select(:title).for_key(issue.id)
22
+
23
+ assert_equal [:title], query.select_values
24
+ end
25
+
26
+ test 'only column names' do
27
+ Issue.create title: 'foo', description: 'bar'
28
+ foo_issue_columns = Issue.columns.first
29
+ assert_equal ['created_at', 'description', 'title', 'updated_at'], foo_issue_columns[foo_issue_columns.keys.first]
30
+ end
31
+
32
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::ScopingTest < CassandraObject::TestCase
4
+ test "scope" do
5
+ assert_kind_of CassandraObject::Scope, Issue.scope
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::TimestampsTest < CassandraObject::TestCase
4
+ test 'timestamps set on create' do
5
+ issue = Issue.create
6
+
7
+ assert_in_delta Time.now.to_i, issue.created_at.to_i, 3
8
+ assert_in_delta Time.now.to_i, issue.updated_at.to_i, 3
9
+ end
10
+
11
+ test 'updated_at set on change' do
12
+ issue = Issue.create
13
+
14
+ issue.updated_at = nil
15
+ issue.description = 'lol'
16
+ issue.save
17
+
18
+ assert_in_delta Time.now.to_i, issue.updated_at.to_i, 3
19
+ end
20
+
21
+ test 'created_at sets only if nil' do
22
+ time = 5.days.ago
23
+ issue = Issue.create created_at: time
24
+
25
+ assert_equal time, issue.created_at
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Types::ArrayTypeTest < CassandraObject::Types::TestCase
4
+ test 'encode' do
5
+ assert_equal ['1', '2'].to_json, coder.encode(['1', '2'])
6
+
7
+ assert_raise ArgumentError do
8
+ coder.encode('wtf')
9
+ end
10
+ end
11
+
12
+ test 'decode' do
13
+ assert_equal ['1', '2'], coder.decode(['1', '2'].to_json)
14
+ assert_nil coder.decode(nil)
15
+ assert_nil coder.decode('')
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Types::BaseTypeTest < CassandraObject::Types::TestCase
4
+ test 'default' do
5
+ assert_nil coder.default
6
+ assert_equal '5', CassandraObject::Types::BaseType.new(default: '5').default
7
+ assert_equal 5.object_id, CassandraObject::Types::BaseType.new(default: 5).default.object_id
8
+ end
9
+
10
+ test 'encode' do
11
+ assert_equal '1', coder.encode(1)
12
+ assert_equal '', coder.encode(nil)
13
+ assert_equal '1', coder.encode('1')
14
+ end
15
+
16
+ test 'decode' do
17
+ assert_equal 'abc', coder.decode('abc')
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Types::BooleanTypeTest < CassandraObject::Types::TestCase
4
+ test 'encode' do
5
+ assert_equal '1', coder.encode(true)
6
+ assert_equal '1', coder.encode('true')
7
+ assert_equal '1', coder.encode('1')
8
+
9
+ assert_equal '0', coder.encode(false)
10
+ assert_equal '0', coder.encode('false')
11
+ assert_equal '0', coder.encode('0')
12
+ assert_equal '0', coder.encode('')
13
+
14
+ assert_raise ArgumentError do
15
+ coder.encode('wtf')
16
+ end
17
+ end
18
+
19
+ test 'decode' do
20
+ assert_equal true, coder.decode('1')
21
+ assert_equal false, coder.decode('0')
22
+ # assert_nil coder.decode(nil)
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Types::DateTypeTest < CassandraObject::Types::TestCase
4
+ test 'encode' do
5
+ assert_equal '2004-04-25', coder.encode(Date.new(2004, 4, 25))
6
+ end
7
+
8
+ test 'decode' do
9
+ assert_equal Date.new(2004, 4, 25), coder.decode('2004-04-25')
10
+ end
11
+
12
+ test 'decoding a blank dates' do
13
+ assert_nil coder.decode('')
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Types::FloatTypeTest < CassandraObject::Types::TestCase
4
+ test 'encode' do
5
+ assert_equal '5.01', coder.encode(5.01)
6
+
7
+ assert_raise ArgumentError do
8
+ coder.encode('x')
9
+ end
10
+ end
11
+
12
+ test 'decode' do
13
+ assert_equal 0.0, coder.decode('xyz')
14
+ assert_equal 3.14, coder.decode('3.14')
15
+ assert_equal 5, coder.decode('5')
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Types::IntegerTypeTest < CassandraObject::Types::TestCase
4
+ test 'encode' do
5
+ assert_equal('3', coder.encode(3))
6
+ assert_equal('-3', coder.encode(-3))
7
+
8
+ assert_raise ArgumentError do
9
+ coder.encode('xx')
10
+ end
11
+ end
12
+
13
+ test 'decode' do
14
+ assert_nil coder.decode('')
15
+ assert_equal(0, coder.decode('abc'))
16
+ assert_equal(3, coder.decode('3'))
17
+ assert_equal(-3, coder.decode('-3'))
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Types::JsonTypeTest < CassandraObject::Types::TestCase
4
+ test 'encode' do
5
+ assert_equal({a: 'b'}.to_json, coder.encode(a: 'b'))
6
+ assert_equal '-3', coder.encode(-3)
7
+ end
8
+
9
+ test 'decode' do
10
+ assert_equal({'a' => 'b'}, coder.decode({'a' => 'b'}.to_json))
11
+ end
12
+
13
+ test 'encode array' do
14
+ assert_equal(['a', 'b'].to_json, coder.encode(['a', 'b']))
15
+ assert_equal '-3', coder.encode(-3)
16
+ end
17
+
18
+ test 'decode array' do
19
+ assert_equal(['a', 'b'], coder.decode(['a', 'b'].to_json))
20
+ end
21
+
22
+
23
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::Types::StringTypeTest < CassandraObject::Types::TestCase
4
+ test 'encode' do
5
+ assert_equal 'abc', coder.encode('abc')
6
+
7
+ assert_raise ArgumentError do
8
+ coder.encode(123)
9
+ end
10
+ end
11
+
12
+ test 'encode as utf' do
13
+ assert_equal(
14
+ '123'.force_encoding('UTF-8').encoding,
15
+ coder.encode('123'.force_encoding('ASCII-8BIT')).encoding
16
+ )
17
+ end
18
+
19
+ test 'encode frozen as utf' do
20
+ assert_equal(
21
+ '123'.force_encoding('UTF-8').encoding,
22
+ coder.encode('123'.force_encoding('ASCII-8BIT').freeze).encoding
23
+ )
24
+ end
25
+ end