gotime-cassandra_object 2.8.3 → 2.8.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/Rakefile +0 -1
- data/gotime-cassandra_object.gemspec +1 -1
- data/lib/cassandra_object/attribute_methods.rb +3 -41
- data/lib/cassandra_object/attribute_methods/typecasting.rb +52 -0
- data/lib/cassandra_object/base.rb +2 -1
- data/lib/cassandra_object/batches.rb +1 -1
- data/lib/cassandra_object/finder_methods.rb +1 -1
- data/lib/cassandra_object/persistence.rb +8 -7
- data/lib/gotime-cassandra_object.rb +1 -0
- data/test/attribute_methods/definition_test.rb +1 -1
- data/test/attribute_methods/typecasting_test.rb +87 -0
- data/test/attribute_methods_test.rb +17 -51
- data/test/batches_test.rb +2 -2
- data/test/test_helper.rb +2 -4
- metadata +10 -8
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -4,51 +4,13 @@ module CassandraObject
|
|
4
4
|
include ActiveModel::AttributeMethods
|
5
5
|
|
6
6
|
included do
|
7
|
-
|
8
|
-
|
7
|
+
alias :[] :read_attribute
|
8
|
+
alias :[]= :write_attribute
|
9
9
|
|
10
10
|
attribute_method_suffix("", "=")
|
11
|
-
|
12
|
-
%w(array boolean date float integer json string time time_with_zone).each do |type|
|
13
|
-
instance_eval <<-EOV, __FILE__, __LINE__ + 1
|
14
|
-
def #{type}(name, options = {}) # def string(name, options = {})
|
15
|
-
attribute(name, options.update(type: :#{type})) # attribute(name, options.update(type: :string))
|
16
|
-
end # end
|
17
|
-
EOV
|
18
|
-
end
|
19
11
|
end
|
20
12
|
|
21
13
|
module ClassMethods
|
22
|
-
def inherited(child)
|
23
|
-
super
|
24
|
-
child.attribute_definitions = attribute_definitions.dup
|
25
|
-
end
|
26
|
-
|
27
|
-
#
|
28
|
-
# attribute :name, type: :string
|
29
|
-
# attribute :ammo, type: Ammo, coder: AmmoCodec
|
30
|
-
#
|
31
|
-
def attribute(name, options)
|
32
|
-
type = options.delete :type
|
33
|
-
coder = options.delete :coder
|
34
|
-
|
35
|
-
if type.is_a?(Symbol)
|
36
|
-
coder = CassandraObject::Type.get_coder(type) || (raise "Unknown type #{type}")
|
37
|
-
elsif coder.nil?
|
38
|
-
raise "Must supply a :coder for #{name}"
|
39
|
-
end
|
40
|
-
|
41
|
-
attribute_definitions[name.to_sym] = AttributeMethods::Definition.new(name, coder, options)
|
42
|
-
end
|
43
|
-
|
44
|
-
def instantiate_attribute(record, name, value)
|
45
|
-
if attribute_definition = attribute_definitions[name.to_sym]
|
46
|
-
attribute_definition.instantiate(record, value)
|
47
|
-
else
|
48
|
-
raise NoMethodError, "Unknown attribute #{name.inspect}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
14
|
def define_attribute_methods
|
53
15
|
return if attribute_methods_generated?
|
54
16
|
super(attribute_definitions.keys)
|
@@ -61,7 +23,7 @@ module CassandraObject
|
|
61
23
|
end
|
62
24
|
|
63
25
|
def write_attribute(name, value)
|
64
|
-
@attributes[name.to_s] = self.class.
|
26
|
+
@attributes[name.to_s] = self.class.typecast_attribute(self, name, value)
|
65
27
|
end
|
66
28
|
|
67
29
|
def read_attribute(name)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module AttributeMethods
|
3
|
+
module Typecasting
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :attribute_definitions
|
8
|
+
self.attribute_definitions = {}
|
9
|
+
|
10
|
+
%w(array boolean date float integer json string time time_with_zone).each do |type|
|
11
|
+
instance_eval <<-EOV, __FILE__, __LINE__ + 1
|
12
|
+
def #{type}(name, options = {}) # def string(name, options = {})
|
13
|
+
attribute(name, options.update(type: :#{type})) # attribute(name, options.update(type: :string))
|
14
|
+
end # end
|
15
|
+
EOV
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def inherited(child)
|
21
|
+
super
|
22
|
+
child.attribute_definitions = attribute_definitions.dup
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# attribute :name, type: :string
|
27
|
+
# attribute :ammo, type: Ammo, coder: AmmoCodec
|
28
|
+
#
|
29
|
+
def attribute(name, options)
|
30
|
+
type = options.delete :type
|
31
|
+
coder = options.delete :coder
|
32
|
+
|
33
|
+
if type.is_a?(Symbol)
|
34
|
+
coder = CassandraObject::Type.get_coder(type) || (raise "Unknown type #{type}")
|
35
|
+
elsif coder.nil?
|
36
|
+
raise "Must supply a :coder for #{name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
attribute_definitions[name.to_sym] = AttributeMethods::Definition.new(name, coder, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def typecast_attribute(record, name, value)
|
43
|
+
if attribute_definition = attribute_definitions[name.to_sym]
|
44
|
+
attribute_definition.instantiate(record, value)
|
45
|
+
else
|
46
|
+
raise NoMethodError, "Unknown attribute #{name.inspect}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -36,6 +36,7 @@ module CassandraObject
|
|
36
36
|
include Batches
|
37
37
|
include AttributeMethods
|
38
38
|
include AttributeMethods::Dirty
|
39
|
+
include AttributeMethods::Typecasting
|
39
40
|
include Callbacks
|
40
41
|
include Validations
|
41
42
|
include Associations
|
@@ -56,7 +57,7 @@ module CassandraObject
|
|
56
57
|
self.attributes = attributes
|
57
58
|
attribute_definitions.each do |attr, attribute_definition|
|
58
59
|
unless attribute_exists?(attr)
|
59
|
-
self.attributes[attr.to_s] = self.class.
|
60
|
+
self.attributes[attr.to_s] = self.class.typecast_attribute(self, attr, nil)
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
@@ -24,7 +24,7 @@ module CassandraObject
|
|
24
24
|
def all(options = {})
|
25
25
|
limit = options[:limit] || 100
|
26
26
|
results = ActiveSupport::Notifications.instrument("get_range.cassandra_object", column_family: column_family, key_count: limit) do
|
27
|
-
connection.get_range(column_family, key_count: limit, consistency: thrift_read_consistency)
|
27
|
+
connection.get_range(column_family, key_count: limit, consistency: thrift_read_consistency, count: 500)
|
28
28
|
end
|
29
29
|
|
30
30
|
results.map do |k, v|
|
@@ -22,11 +22,12 @@ module CassandraObject
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def write(key, attributes, schema_version)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
attributes = encode_attributes(attributes, schema_version)
|
26
|
+
ActiveSupport::Notifications.instrument("insert.cassandra_object", column_family: column_family, key: key, attributes: attributes) do
|
27
|
+
connection.insert(column_family, key.to_s, attributes, consistency: thrift_write_consistency)
|
28
|
+
# if nil_attributes.any?
|
29
|
+
# connection.remove(connection, key.to_s, *nil_attributes)
|
30
|
+
# end
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
@@ -36,7 +37,7 @@ module CassandraObject
|
|
36
37
|
object.instance_variable_set("@key", parse_key(key)) if key
|
37
38
|
object.instance_variable_set("@new_record", false)
|
38
39
|
object.instance_variable_set("@destroyed", false)
|
39
|
-
object.instance_variable_set("@attributes",
|
40
|
+
object.instance_variable_set("@attributes", typecast_attributes(object, attributes))
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
@@ -51,7 +52,7 @@ module CassandraObject
|
|
51
52
|
encoded
|
52
53
|
end
|
53
54
|
|
54
|
-
def
|
55
|
+
def typecast_attributes(object, attributes)
|
55
56
|
attributes = attributes.symbolize_keys
|
56
57
|
Hash[attribute_definitions.map { |k, attribute_definition| [k.to_s, attribute_definition.instantiate(object, attributes[k])] }]
|
57
58
|
end
|
@@ -4,7 +4,7 @@ class CassandraObject::AttributeMethods::DefinitionTest < CassandraObject::TestC
|
|
4
4
|
class TestType < CassandraObject::Types::BaseType
|
5
5
|
end
|
6
6
|
|
7
|
-
test '
|
7
|
+
test 'typecast' do
|
8
8
|
definition = CassandraObject::AttributeMethods::Definition.new(:foo, TestType, {a: :b})
|
9
9
|
|
10
10
|
assert_equal 'foo', definition.name
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CassandraObject::AttributeMethods::TypecastingTest < CassandraObject::TestCase
|
4
|
+
class CustomType
|
5
|
+
end
|
6
|
+
|
7
|
+
class CustomCoder < CassandraObject::Types::BaseType
|
8
|
+
end
|
9
|
+
|
10
|
+
class TestIssue < CassandraObject::Base
|
11
|
+
key :uuid
|
12
|
+
self.column_family = 'Issues'
|
13
|
+
|
14
|
+
attribute :custom_column, type: CustomType, coder: CustomCoder
|
15
|
+
boolean :enabled
|
16
|
+
float :rating
|
17
|
+
integer :price
|
18
|
+
json :orders
|
19
|
+
string :name
|
20
|
+
end
|
21
|
+
|
22
|
+
class TestChildIssue < TestIssue
|
23
|
+
string :description
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'attributes not shared' do
|
27
|
+
assert_nothing_raised { Issue.new.description }
|
28
|
+
assert_raise(NoMethodError) { TestIssue.new.description }
|
29
|
+
assert_nothing_raised { TestChildIssue.new.description }
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'custom attribute definer' do
|
33
|
+
model_attribute = TestIssue.attribute_definitions[:custom_column]
|
34
|
+
|
35
|
+
assert_kind_of CustomCoder, model_attribute.coder
|
36
|
+
assert_equal 'custom_column', model_attribute.name
|
37
|
+
end
|
38
|
+
|
39
|
+
test 'typecast_attribute' do
|
40
|
+
assert_equal 1, TestIssue.typecast_attribute(TestIssue.new, 'price', 1)
|
41
|
+
assert_equal 1, TestIssue.typecast_attribute(TestIssue.new, :price, 1)
|
42
|
+
|
43
|
+
assert_raise NoMethodError do
|
44
|
+
TestIssue.typecast_attribute(TestIssue.new, 'wtf', 1)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
test 'boolean attribute' do
|
49
|
+
issue = TestIssue.create! enabled: '1'
|
50
|
+
assert_equal true, issue.enabled
|
51
|
+
|
52
|
+
issue = TestIssue.find issue.id
|
53
|
+
assert_equal true, issue.enabled
|
54
|
+
end
|
55
|
+
|
56
|
+
test 'float attribute' do
|
57
|
+
issue = TestIssue.create! rating: '4.5'
|
58
|
+
assert_equal 4.5, issue.rating
|
59
|
+
|
60
|
+
issue = TestIssue.find issue.id
|
61
|
+
assert_equal(4.5, issue.rating)
|
62
|
+
end
|
63
|
+
|
64
|
+
test 'integer attribute' do
|
65
|
+
issue = TestIssue.create! price: '101'
|
66
|
+
assert_equal 101, issue.price
|
67
|
+
|
68
|
+
issue = TestIssue.find issue.id
|
69
|
+
assert_equal(101, issue.price)
|
70
|
+
end
|
71
|
+
|
72
|
+
test 'json attribute' do
|
73
|
+
issue = TestIssue.create! orders: {'a' => 'b'}
|
74
|
+
assert_equal({'a' => 'b'}, issue.orders)
|
75
|
+
|
76
|
+
issue = TestIssue.find issue.id
|
77
|
+
assert_equal({'a' => 'b'}, issue.orders)
|
78
|
+
end
|
79
|
+
|
80
|
+
test 'string attribute' do
|
81
|
+
issue = TestIssue.create! name: 'hola'
|
82
|
+
assert_equal('hola', issue.name)
|
83
|
+
|
84
|
+
issue = TestIssue.find issue.id
|
85
|
+
assert_equal('hola', issue.name)
|
86
|
+
end
|
87
|
+
end
|
@@ -1,54 +1,31 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class CassandraObject::AttributeMethodsTest < CassandraObject::TestCase
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
class CustomCoder < CassandraObject::Types::BaseType
|
8
|
-
end
|
9
|
-
|
10
|
-
class TestIssue < CassandraObject::Base
|
11
|
-
key :uuid
|
12
|
-
self.column_family = 'Issues'
|
13
|
-
|
14
|
-
attribute :custom_column, type: CustomType, coder: CustomCoder
|
15
|
-
integer :price
|
16
|
-
json :orders
|
17
|
-
end
|
18
|
-
|
19
|
-
class TestChildIssue < TestIssue
|
20
|
-
string :description
|
21
|
-
end
|
4
|
+
test 'read and write attributes' do
|
5
|
+
issue = Issue.new
|
6
|
+
assert_nil issue.read_attribute(:description)
|
22
7
|
|
23
|
-
|
24
|
-
|
8
|
+
issue.write_attribute(:description, nil)
|
9
|
+
assert_nil issue.read_attribute(:description)
|
25
10
|
|
26
|
-
|
27
|
-
assert_equal '
|
11
|
+
issue.write_attribute(:description, 'foo')
|
12
|
+
assert_equal 'foo', issue.read_attribute(:description)
|
28
13
|
end
|
29
14
|
|
30
|
-
test '
|
31
|
-
issue =
|
32
|
-
|
33
|
-
issue = TestIssue.find issue.id
|
34
|
-
|
35
|
-
assert_equal({'a' => 'b'}, issue.orders)
|
36
|
-
end
|
15
|
+
test 'hash accessor aliases' do
|
16
|
+
issue = Issue.new
|
37
17
|
|
38
|
-
|
39
|
-
assert_equal 1, TestIssue.instantiate_attribute(TestIssue.new, 'price', 1)
|
40
|
-
assert_equal 1, TestIssue.instantiate_attribute(TestIssue.new, :price, 1)
|
18
|
+
issue[:description] = 'bar'
|
41
19
|
|
42
|
-
|
43
|
-
TestIssue.instantiate_attribute(TestIssue.new, 'wtf', 1)
|
44
|
-
end
|
20
|
+
assert_equal 'bar', issue[:description]
|
45
21
|
end
|
46
22
|
|
47
|
-
test '
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
23
|
+
# test 'attribute_exists' do
|
24
|
+
# assert !Issue.new.attribute_exists?(:description)
|
25
|
+
# assert Issue.new(description: nil).attribute_exists?(:description)
|
26
|
+
# assert Issue.new(description: false).attribute_exists?(:description)
|
27
|
+
# assert Issue.new(description: 'hey').attribute_exists?(:description)
|
28
|
+
# end
|
52
29
|
|
53
30
|
test 'attributes setter' do
|
54
31
|
issue = Issue.new
|
@@ -59,15 +36,4 @@ class CassandraObject::AttributeMethodsTest < CassandraObject::TestCase
|
|
59
36
|
|
60
37
|
assert_equal 'foo', issue.description
|
61
38
|
end
|
62
|
-
|
63
|
-
test 'read and write attributes' do
|
64
|
-
issue = Issue.new
|
65
|
-
assert_nil issue.read_attribute(:description)
|
66
|
-
|
67
|
-
issue.write_attribute(:description, nil)
|
68
|
-
assert_nil issue.read_attribute(:description)
|
69
|
-
|
70
|
-
issue.write_attribute(:description, 'foo')
|
71
|
-
assert_equal 'foo', issue.read_attribute(:description)
|
72
|
-
end
|
73
39
|
end
|
data/test/batches_test.rb
CHANGED
@@ -17,12 +17,12 @@ class CassandraObject::BatchesTest < CassandraObject::TestCase
|
|
17
17
|
Issue.create
|
18
18
|
Issue.create
|
19
19
|
Issue.create
|
20
|
-
|
20
|
+
|
21
21
|
issue_batches = []
|
22
22
|
Issue.find_in_batches(batch_size: 2) do |issues|
|
23
23
|
issue_batches << issues
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
assert_equal 2, issue_batches.size
|
27
27
|
assert issue_batches.any? { |issues| issues.size == 2 }
|
28
28
|
assert issue_batches.any? { |issues| issues.size == 1 }
|
data/test/test_helper.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'bundler/setup'
|
3
|
-
require '
|
4
|
-
require
|
5
|
-
require 'gotime-cassandra_object'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
Bundler.require(:default, :test)
|
6
4
|
|
7
5
|
CassandraObject::Base.establish_connection(
|
8
6
|
keyspace: 'place_directory_development',
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gotime-cassandra_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.8.
|
4
|
+
version: 2.8.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-11-
|
13
|
+
date: 2011-11-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activemodel
|
17
|
-
requirement: &
|
17
|
+
requirement: &70143745006900 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '3.0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70143745006900
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: cassandra
|
28
|
-
requirement: &
|
28
|
+
requirement: &70143745002740 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: 0.12.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70143745002740
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: bundler
|
39
|
-
requirement: &
|
39
|
+
requirement: &70143744999540 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
version: 1.0.0
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *70143744999540
|
48
48
|
description: Cassandra ActiveModel
|
49
49
|
email: gems@gotime.com
|
50
50
|
executables: []
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- lib/cassandra_object/attribute_methods.rb
|
67
67
|
- lib/cassandra_object/attribute_methods/definition.rb
|
68
68
|
- lib/cassandra_object/attribute_methods/dirty.rb
|
69
|
+
- lib/cassandra_object/attribute_methods/typecasting.rb
|
69
70
|
- lib/cassandra_object/base.rb
|
70
71
|
- lib/cassandra_object/batches.rb
|
71
72
|
- lib/cassandra_object/callbacks.rb
|
@@ -115,6 +116,7 @@ files:
|
|
115
116
|
- test/active_model_test.rb
|
116
117
|
- test/attribute_methods/definition_test.rb
|
117
118
|
- test/attribute_methods/dirty_test.rb
|
119
|
+
- test/attribute_methods/typecasting_test.rb
|
118
120
|
- test/attribute_methods_test.rb
|
119
121
|
- test/base_test.rb
|
120
122
|
- test/batches_test.rb
|