gotime-cassandra_object 2.7.0 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -6,8 +6,11 @@ Cassandra Object uses ActiveModel to mimic much of the behavior in ActiveRecord.
6
6
 
7
7
  Add the following to your Gemfile:
8
8
 
9
+ gem 'cassandra', require: '0.8'
9
10
  gem 'gotime-cassandra_object'
10
11
 
12
+ Change the version of Cassandra accordingly. Recent versions have not been backward compatible.
13
+
11
14
  == Defining Models
12
15
 
13
16
  class Widget < CassandraObject::Base
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'gotime-cassandra_object'
5
- s.version = '2.7.0'
5
+ s.version = '2.7.1'
6
6
  s.description = 'Cassandra ActiveModel'
7
7
  s.summary = 'Cassandra ActiveModel'
8
8
 
@@ -1,31 +1,14 @@
1
1
  module CassandraObject
2
- class Attribute
3
- attr_reader :name, :coder, :expected_type
4
- def initialize(name, type_mapping, options)
5
- @name = name.to_s
6
- @coder = type_mapping.coder.new(options)
7
- @expected_type = type_mapping.expected_type
8
- end
9
-
10
- def instantiate(record, value)
11
- value ||= coder.default
12
- return unless value
13
-
14
- value = value.kind_of?(expected_type) ? value : coder.decode(value)
15
- coder.wrap(record, name, value)
16
- end
17
- end
18
-
19
- module Attributes
2
+ module AttributeMethods
20
3
  extend ActiveSupport::Concern
21
4
  include ActiveModel::AttributeMethods
22
5
 
23
6
  included do
24
- class_attribute :model_attributes
25
- self.model_attributes = {}
7
+ class_attribute :attribute_definitions
8
+ self.attribute_definitions = {}
26
9
 
27
10
  attribute_method_suffix("", "=")
28
-
11
+
29
12
  %w(array boolean date float integer time time_with_zone string).each do |type|
30
13
  instance_eval <<-EOV, __FILE__, __LINE__ + 1
31
14
  def #{type}(name, options = {}) # def string(name, options = {})
@@ -38,7 +21,7 @@ module CassandraObject
38
21
  module ClassMethods
39
22
  def inherited(child)
40
23
  super
41
- child.model_attributes = model_attributes.dup
24
+ child.attribute_definitions = attribute_definitions.dup
42
25
  end
43
26
 
44
27
  #
@@ -47,7 +30,7 @@ module CassandraObject
47
30
  #
48
31
  def attribute(name, options)
49
32
  expected_type = options.delete :type
50
- coder = options.delete :coder
33
+ coder = options.delete :coder
51
34
 
52
35
  if expected_type.is_a?(Symbol)
53
36
  type_mapping = CassandraObject::Type.get_mapping(expected_type) || (raise "Unknown type #{type}")
@@ -57,7 +40,7 @@ module CassandraObject
57
40
  type_mapping = CassandraObject::Type::TypeMapping.new(expected_type, coder)
58
41
  end
59
42
 
60
- model_attributes[name.to_sym] = Attribute.new(name, type_mapping, options)
43
+ attribute_definitions[name.to_sym] = AttributeMethods::Definition.new(name, type_mapping, options)
61
44
  end
62
45
 
63
46
  def json(name, options = {})
@@ -65,15 +48,15 @@ module CassandraObject
65
48
  end
66
49
 
67
50
  def instantiate_attribute(record, name, value)
68
- if model_attribute = model_attributes[name.to_sym]
69
- model_attribute.instantiate(record, value)
51
+ if attribute_definition = attribute_definitions[name.to_sym]
52
+ attribute_definition.instantiate(record, value)
70
53
  else
71
54
  raise NoMethodError, "Unknown attribute #{name.inspect}"
72
55
  end
73
56
  end
74
57
 
75
58
  def define_attribute_methods
76
- super(model_attributes.keys)
59
+ super(attribute_definitions.keys)
77
60
  end
78
61
  end
79
62
 
@@ -107,7 +90,7 @@ module CassandraObject
107
90
 
108
91
  protected
109
92
  def attribute_method?(name)
110
- !!model_attributes[name.to_sym]
93
+ !!attribute_definitions[name.to_sym]
111
94
  end
112
95
 
113
96
  private
@@ -0,0 +1,20 @@
1
+ module CassandraObject
2
+ module AttributeMethods
3
+ class Definition
4
+ attr_reader :name, :coder, :expected_type
5
+ def initialize(name, type_mapping, options)
6
+ @name = name.to_s
7
+ @coder = type_mapping.coder.new(options)
8
+ @expected_type = type_mapping.expected_type
9
+ end
10
+
11
+ def instantiate(record, value)
12
+ value ||= coder.default
13
+ return unless value
14
+
15
+ value = value.kind_of?(expected_type) ? value : coder.decode(value)
16
+ coder.wrap(record, name, value)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,44 @@
1
+ module CassandraObject
2
+ module AttributeMethods
3
+ module Dirty
4
+ extend ActiveSupport::Concern
5
+ include ActiveModel::Dirty
6
+
7
+ # Attempts to +save+ the record and clears changed attributes if successful.
8
+ def save(*) #:nodoc:
9
+ if status = super
10
+ @previously_changed = changes
11
+ @changed_attributes.clear
12
+ end
13
+ status
14
+ end
15
+
16
+ # Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
17
+ def save!(*) #:nodoc:
18
+ super.tap do
19
+ @previously_changed = changes
20
+ @changed_attributes.clear
21
+ end
22
+ end
23
+
24
+ # <tt>reload</tt> the record and clears changed attributes.
25
+ def reload
26
+ super.tap do
27
+ @previously_changed.try :clear
28
+ @changed_attributes.clear
29
+ end
30
+ end
31
+
32
+ def write_attribute(name, value)
33
+ name = name.to_s
34
+ old = read_attribute(name)
35
+
36
+ super
37
+
38
+ unless attribute_changed?(name) || old == read_attribute(name)
39
+ changed_attributes[name] = old
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -31,14 +31,14 @@ module CassandraObject
31
31
  include Connection
32
32
  include Consistency
33
33
  include Identity
34
- include Attributes
34
+ include FinderMethods
35
35
  include Persistence
36
+ include Batches
37
+ include AttributeMethods
38
+ include AttributeMethods::Dirty
36
39
  include Callbacks
37
- include Dirty
38
40
  include Validations
39
41
  include Associations
40
- include Batches
41
- include FinderMethods
42
42
  include Timestamps
43
43
 
44
44
  attr_reader :attributes
@@ -54,9 +54,9 @@ module CassandraObject
54
54
  @destroyed = false
55
55
  @attributes = {}
56
56
  self.attributes = attributes
57
- model_attributes.each do |k, model_attribute|
58
- unless read_attribute(k)
59
- write_attribute(k, model_attribute.instantiate(self, nil))
57
+ attribute_definitions.each do |attr, attribute_definition|
58
+ unless read_attribute(attr)
59
+ write_attribute(attr, attribute_definition.instantiate(self, nil))
60
60
  end
61
61
  end
62
62
 
@@ -69,7 +69,7 @@ module CassandraObject
69
69
 
70
70
  def hash
71
71
  id.hash
72
- end
72
+ end
73
73
 
74
74
  def ==(comparison_object)
75
75
  comparison_object.equal?(self) ||
@@ -45,14 +45,14 @@ module CassandraObject
45
45
  # cassandra stores bytes, not strings, so it has no concept of encodings. The ruby thrift gem
46
46
  # expects all strings to be encoded as ascii-8bit.
47
47
  # don't attempt to encode columns that are nil
48
- memo[column_name.to_s] = value.nil? ? '' : model_attributes[column_name.to_sym].coder.encode(value).force_encoding('ASCII-8BIT')
48
+ memo[column_name.to_s] = value.nil? ? '' : attribute_definitions[column_name.to_sym].coder.encode(value).force_encoding('ASCII-8BIT')
49
49
  memo
50
50
  end.merge({"schema_version" => schema_version.to_s})
51
51
  end
52
52
 
53
53
  def instantiate_attributes(object, attributes)
54
54
  attributes = attributes.symbolize_keys
55
- Hash[model_attributes.map { |k, model_attribute| [k.to_s, model_attribute.instantiate(object, attributes[k])] }]
55
+ Hash[attribute_definitions.map { |k, attribute_definition| [k.to_s, attribute_definition.instantiate(object, attributes[k])] }]
56
56
  end
57
57
  end
58
58
 
@@ -13,6 +13,13 @@ module CassandraObject
13
13
  end
14
14
 
15
15
  def <<(obj)
16
+ modifying do
17
+ super
18
+ setify!
19
+ end
20
+ end
21
+
22
+ def delete(obj)
16
23
  modifying do
17
24
  super
18
25
  end
@@ -32,7 +39,6 @@ module CassandraObject
32
39
  end
33
40
 
34
41
  result = yield
35
- setify!
36
42
 
37
43
  if !record.changed_attributes.key?(name) && original != self
38
44
  record.changed_attributes[name] = original
@@ -6,8 +6,7 @@ module CassandraObject
6
6
 
7
7
  autoload :Base
8
8
  autoload :Connection
9
- autoload :Attributes
10
- autoload :Dirty
9
+ autoload :AttributeMethods
11
10
  autoload :Consistency
12
11
  autoload :Persistence
13
12
  autoload :Callbacks
@@ -25,6 +24,15 @@ module CassandraObject
25
24
  autoload :Type
26
25
  autoload :Schema
27
26
 
27
+ module AttributeMethods
28
+ extend ActiveSupport::Autoload
29
+
30
+ eager_autoload do
31
+ autoload :Definition
32
+ autoload :Dirty
33
+ end
34
+ end
35
+
28
36
  module Tasks
29
37
  extend ActiveSupport::Autoload
30
38
  autoload :Keyspace
File without changes
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::AttributeMethods::DirtyTest < CassandraObject::TestCase
4
+ test 'save clears dirty' do
5
+ record = temp_object do
6
+ string :name
7
+ end.new name: 'foo'
8
+
9
+ assert record.changed?
10
+
11
+ record.save!
12
+
13
+ assert !record.changed?
14
+ end
15
+
16
+ test 'reload clears dirty' do
17
+ record = temp_object do
18
+ string :name
19
+ end.create! name: 'foo'
20
+
21
+ record.name = 'bar'
22
+ assert record.changed?
23
+
24
+ record.reload
25
+
26
+ assert !record.changed?
27
+ end
28
+
29
+ test 'typecase before dirty check' do
30
+ record = temp_object do
31
+ float :price
32
+ end.create(price: 5.01)
33
+
34
+ record.price = '5.01'
35
+ assert !record.changed?
36
+
37
+ record.price = '7.12'
38
+ assert record.changed?
39
+ end
40
+ end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class CassandraObject::AttributesTest < CassandraObject::TestCase
3
+ class CassandraObject::AttributeMethodsTest < CassandraObject::TestCase
4
4
  class CustomType
5
5
  end
6
6
 
@@ -21,7 +21,7 @@ class CassandraObject::AttributesTest < CassandraObject::TestCase
21
21
  end
22
22
 
23
23
  test 'custom attribute definer' do
24
- model_attribute = TestIssue.model_attributes[:custom_column]
24
+ model_attribute = TestIssue.attribute_definition[:custom_column]
25
25
 
26
26
  assert_kind_of CustomCoder, model_attribute.coder
27
27
  assert_equal CustomType, model_attribute.expected_type
data/test/test_helper.rb CHANGED
@@ -19,10 +19,18 @@ module CassandraObject
19
19
  teardown do
20
20
  Issue.delete_all
21
21
  end
22
-
22
+
23
23
  def connection
24
24
  CassandraObject::Base.connection
25
25
  end
26
+
27
+ def temp_object(&block)
28
+ Class.new(CassandraObject::Base) do
29
+ key :uuid
30
+ self.column_family = 'Issues'
31
+ instance_eval(&block)
32
+ end
33
+ end
26
34
  end
27
35
 
28
36
  module Types
@@ -19,16 +19,24 @@ class CassandraObject::Types::ArrayTypeTest < CassandraObject::Types::TestCase
19
19
  array :favorite_colors, unique: true
20
20
  end
21
21
 
22
- test 'wrap' do
22
+ test 'append marks dirty' do
23
23
  issue = TestIssue.create favorite_colors: []
24
24
  assert !issue.changed?
25
- assert_kind_of Array, issue.favorite_colors
26
25
 
27
26
  issue.favorite_colors << 'red'
28
27
  assert issue.changed?
29
28
  assert_equal({'favorite_colors' => [[], ['red']]}, issue.changes)
30
29
  end
31
30
 
31
+ test 'delete marks dirty' do
32
+ issue = TestIssue.create favorite_colors: ['red']
33
+ assert !issue.changed?
34
+
35
+ issue.favorite_colors.delete('red')
36
+ assert issue.changed?
37
+ assert_equal({'favorite_colors' => [['red'], []]}, issue.changes)
38
+ end
39
+
32
40
  test 'unique array' do
33
41
  issue = TestIssue.create favorite_colors: ['blue', 'red']
34
42
 
@@ -5,7 +5,7 @@ class CassandraObject::Types::BooleanTypeTest < CassandraObject::Types::TestCase
5
5
  assert_equal '1', coder.encode(true)
6
6
  assert_equal '1', coder.encode('true')
7
7
  assert_equal '1', coder.encode('1')
8
- coder
8
+
9
9
  assert_equal '0', coder.encode(false)
10
10
  assert_equal '0', coder.encode('false')
11
11
  assert_equal '0', coder.encode('0')
@@ -1,5 +1,20 @@
1
1
  require 'test_helper'
2
2
 
3
- class CassandraObject::Type::FloatTypeTest < CassandraObject::Types::TestCase
4
-
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 3.14, coder.decode('3.14')
14
+ assert_equal 5, coder.decode('5')
15
+
16
+ assert_raise ArgumentError do
17
+ coder.decode('xyz')
18
+ end
19
+ end
5
20
  end
@@ -12,4 +12,16 @@ class CassandraObject::ValidationsTest < CassandraObject::TestCase
12
12
  Issue.reset_callbacks(:validate)
13
13
  end
14
14
  end
15
+
16
+ test 'save!' do
17
+ begin
18
+ Issue.validates(:description, presence: true)
19
+
20
+ Issue.new(description: 'lol').save!
21
+
22
+ assert_raise(CassandraObject::RecordInvalid) { Issue.new(description: '').save! }
23
+ ensure
24
+ Issue.reset_callbacks(:validate)
25
+ end
26
+ end
15
27
  end
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.7.0
4
+ version: 2.7.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -14,7 +14,7 @@ date: 2011-08-30 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activemodel
17
- requirement: &70185349554920 !ruby/object:Gem::Requirement
17
+ requirement: &70132262094800 !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: *70185349554920
25
+ version_requirements: *70132262094800
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: cassandra
28
- requirement: &70185349554140 !ruby/object:Gem::Requirement
28
+ requirement: &70132262094260 !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: *70185349554140
36
+ version_requirements: *70132262094260
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: bundler
39
- requirement: &70185349553500 !ruby/object:Gem::Requirement
39
+ requirement: &70132262093740 !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: *70185349553500
47
+ version_requirements: *70132262093740
48
48
  description: Cassandra ActiveModel
49
49
  email: gems@gotime.com
50
50
  executables: []
@@ -63,7 +63,9 @@ files:
63
63
  - lib/cassandra_object/associations.rb
64
64
  - lib/cassandra_object/associations/one_to_many.rb
65
65
  - lib/cassandra_object/associations/one_to_one.rb
66
- - lib/cassandra_object/attributes.rb
66
+ - lib/cassandra_object/attribute_methods.rb
67
+ - lib/cassandra_object/attribute_methods/definition.rb
68
+ - lib/cassandra_object/attribute_methods/dirty.rb
67
69
  - lib/cassandra_object/base.rb
68
70
  - lib/cassandra_object/batches.rb
69
71
  - lib/cassandra_object/callbacks.rb
@@ -71,7 +73,6 @@ files:
71
73
  - lib/cassandra_object/connection.rb
72
74
  - lib/cassandra_object/consistency.rb
73
75
  - lib/cassandra_object/cursor.rb
74
- - lib/cassandra_object/dirty.rb
75
76
  - lib/cassandra_object/errors.rb
76
77
  - lib/cassandra_object/finder_methods.rb
77
78
  - lib/cassandra_object/generators/migration_generator.rb
@@ -113,13 +114,14 @@ files:
113
114
  - lib/cassandra_object/validations.rb
114
115
  - lib/gotime-cassandra_object.rb
115
116
  - test/active_model_test.rb
116
- - test/attributes_test.rb
117
+ - test/attribute_methods/definition_test.rb
118
+ - test/attribute_methods/dirty_test.rb
119
+ - test/attribute_methods_test.rb
117
120
  - test/base_test.rb
118
121
  - test/batches_test.rb
119
122
  - test/callbacks_test.rb
120
123
  - test/connection_test.rb
121
124
  - test/consistency_test.rb
122
- - test/dirty_test.rb
123
125
  - test/finder_methods_test.rb
124
126
  - test/identity/uuid_key_factory_test.rb
125
127
  - test/identity_test.rb
@@ -162,13 +164,14 @@ specification_version: 3
162
164
  summary: Cassandra ActiveModel
163
165
  test_files:
164
166
  - test/active_model_test.rb
165
- - test/attributes_test.rb
167
+ - test/attribute_methods/definition_test.rb
168
+ - test/attribute_methods/dirty_test.rb
169
+ - test/attribute_methods_test.rb
166
170
  - test/base_test.rb
167
171
  - test/batches_test.rb
168
172
  - test/callbacks_test.rb
169
173
  - test/connection_test.rb
170
174
  - test/consistency_test.rb
171
- - test/dirty_test.rb
172
175
  - test/finder_methods_test.rb
173
176
  - test/identity/uuid_key_factory_test.rb
174
177
  - test/identity_test.rb
@@ -1,42 +0,0 @@
1
- module CassandraObject
2
- module Dirty
3
- extend ActiveSupport::Concern
4
- include ActiveModel::Dirty
5
-
6
- # Attempts to +save+ the record and clears changed attributes if successful.
7
- def save(*) #:nodoc:
8
- if status = super
9
- @previously_changed = changes
10
- @changed_attributes.clear
11
- end
12
- status
13
- end
14
-
15
- # Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
16
- def save!(*) #:nodoc:
17
- super.tap do
18
- @previously_changed = changes
19
- @changed_attributes.clear
20
- end
21
- end
22
-
23
- # <tt>reload</tt> the record and clears changed attributes.
24
- def reload
25
- super.tap do
26
- @previously_changed.try :clear
27
- @changed_attributes.clear
28
- end
29
- end
30
-
31
- def write_attribute(name, value)
32
- name = name.to_s
33
- old = read_attribute(name)
34
-
35
- super
36
-
37
- unless attribute_changed?(name) || old == read_attribute(name)
38
- changed_attributes[name] = old
39
- end
40
- end
41
- end
42
- end
data/test/dirty_test.rb DELETED
@@ -1,28 +0,0 @@
1
- require 'test_helper'
2
-
3
- class CassandraObject::DirtyTest < CassandraObject::TestCase
4
- class TestRecord < CassandraObject::Base
5
- key :uuid
6
- self.column_family = 'Issues'
7
- string :name
8
- end
9
-
10
- test 'save clears dirty' do
11
- record = TestRecord.new name: 'foo'
12
- assert record.changed?
13
-
14
- record.save!
15
-
16
- assert !record.changed?
17
- end
18
-
19
- test 'reload clears dirty' do
20
- record = TestRecord.create! name: 'foo'
21
- record.name = 'bar'
22
- assert record.changed?
23
-
24
- record.reload
25
-
26
- assert !record.changed?
27
- end
28
- end