extendi-cassandra_object 1.0.0

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.
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