gotime-cassandra_object 2.7.0 → 2.7.1

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