gotime-cassandra_object 4.5.1 → 4.6.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 (72) hide show
  1. data/.travis.yml +2 -0
  2. data/Gemfile +5 -1
  3. data/README.rdoc +0 -2
  4. data/gotime-cassandra_object.gemspec +1 -1
  5. data/lib/cassandra_object/attribute_methods.rb +4 -4
  6. data/lib/cassandra_object/attribute_methods/dirty.rb +1 -1
  7. data/lib/cassandra_object/attribute_methods/primary_key.rb +1 -1
  8. data/lib/cassandra_object/attribute_methods/typecasting.rb +9 -6
  9. data/lib/cassandra_object/base.rb +11 -43
  10. data/lib/cassandra_object/belongs_to.rb +1 -1
  11. data/lib/cassandra_object/belongs_to/association.rb +1 -1
  12. data/lib/cassandra_object/belongs_to/reflection.rb +2 -2
  13. data/lib/cassandra_object/config.rb +15 -0
  14. data/lib/cassandra_object/connection.rb +1 -19
  15. data/lib/cassandra_object/consistency.rb +1 -1
  16. data/lib/cassandra_object/core.rb +46 -0
  17. data/lib/cassandra_object/errors.rb +2 -2
  18. data/lib/cassandra_object/identity.rb +1 -1
  19. data/lib/cassandra_object/persistence.rb +21 -7
  20. data/lib/cassandra_object/railtie.rb +1 -1
  21. data/lib/cassandra_object/savepoints.rb +1 -1
  22. data/lib/cassandra_object/schema.rb +30 -15
  23. data/lib/cassandra_object/schema/tasks.rb +8 -4
  24. data/lib/cassandra_object/scope.rb +1 -1
  25. data/lib/cassandra_object/scope/batches.rb +1 -1
  26. data/lib/cassandra_object/scope/finder_methods.rb +1 -1
  27. data/lib/cassandra_object/scope/query_methods.rb +1 -1
  28. data/lib/cassandra_object/tasks/ks.rake +6 -6
  29. data/lib/cassandra_object/types/array_type.rb +1 -1
  30. data/lib/cassandra_object/types/base_type.rb +1 -1
  31. data/lib/cassandra_object/types/boolean_type.rb +2 -2
  32. data/lib/cassandra_object/types/float_type.rb +1 -1
  33. data/lib/cassandra_object/types/integer_type.rb +1 -1
  34. data/lib/cassandra_object/types/json_type.rb +1 -1
  35. data/lib/cassandra_object/types/string_type.rb +1 -1
  36. data/lib/cassandra_object/types/time_type.rb +1 -1
  37. data/lib/cassandra_object/validations.rb +3 -3
  38. data/lib/gotime-cassandra_object.rb +10 -8
  39. data/test/support/connect.rb +3 -3
  40. data/test/support/issue.rb +1 -1
  41. data/test/test_helper.rb +1 -1
  42. data/test/unit/active_model_test.rb +6 -1
  43. data/test/unit/attribute_methods/definition_test.rb +1 -1
  44. data/test/unit/attribute_methods/dirty_test.rb +2 -2
  45. data/test/unit/attribute_methods/primary_key_test.rb +1 -1
  46. data/test/unit/attribute_methods/typecasting_test.rb +28 -2
  47. data/test/unit/base_test.rb +1 -43
  48. data/test/unit/belongs_to/reflection_test.rb +12 -0
  49. data/test/unit/belongs_to_test.rb +1 -1
  50. data/test/unit/callbacks_test.rb +1 -1
  51. data/test/unit/config_test.rb +23 -0
  52. data/test/unit/connection_test.rb +0 -20
  53. data/test/unit/consistency_test.rb +1 -1
  54. data/test/unit/core_test.rb +50 -0
  55. data/test/unit/identity_test.rb +1 -1
  56. data/test/unit/inspect_test.rb +1 -1
  57. data/test/unit/persistence_test.rb +36 -7
  58. data/test/unit/savepoints_test.rb +7 -7
  59. data/test/unit/schema_test.rb +1 -1
  60. data/test/unit/scope/batches_test.rb +4 -4
  61. data/test/unit/scope/finder_methods_test.rb +3 -3
  62. data/test/unit/scope/query_methods_test.rb +1 -1
  63. data/test/unit/scoping_test.rb +1 -1
  64. data/test/unit/timestamps_test.rb +1 -1
  65. data/test/unit/types/array_type_test.rb +3 -3
  66. data/test/unit/types/base_type_test.rb +1 -1
  67. data/test/unit/types/float_type_test.rb +2 -2
  68. data/test/unit/types/integer_type_test.rb +1 -1
  69. data/test/unit/types/string_type_test.rb +1 -1
  70. data/test/unit/types/time_type_test.rb +1 -1
  71. data/test/unit/validations_test.rb +1 -1
  72. metadata +7 -2
data/.travis.yml CHANGED
@@ -1,5 +1,7 @@
1
+ language: ruby
1
2
  services:
2
3
  - cassandra
3
4
  rvm:
4
5
  - 1.9.2
5
6
  - 1.9.3
7
+ env: CQLSH=/usr/local/cassandra/bin/cqlsh
data/Gemfile CHANGED
@@ -2,4 +2,8 @@ source "http://rubygems.org"
2
2
  gemspec
3
3
 
4
4
  gem 'rake'
5
- gem 'mocha'
5
+ gem 'mocha'
6
+
7
+ # group :development, :test do
8
+ # gem 'pry'
9
+ # end
data/README.rdoc CHANGED
@@ -68,5 +68,3 @@ Some lightweight scoping features are available:
68
68
  Widget.where('color' => 'red')
69
69
  Widget.select(['name', 'color'])
70
70
  Widget.limit(10)
71
-
72
-
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'gotime-cassandra_object'
5
- s.version = '4.5.1'
5
+ s.version = '4.6.0'
6
6
  s.description = 'Cassandra ActiveModel'
7
7
  s.summary = 'Cassandra ActiveModel'
8
8
  s.authors = ["Michael Koziarski", "gotime"]
@@ -9,7 +9,7 @@ module CassandraObject
9
9
  else
10
10
  attribute_method_suffix("=")
11
11
  end
12
-
12
+
13
13
  # (Alias for the protected read_attribute method).
14
14
  def [](attr_name)
15
15
  read_attribute(attr_name)
@@ -26,11 +26,11 @@ module CassandraObject
26
26
  def define_attribute_methods
27
27
  return if attribute_methods_generated?
28
28
  super(attribute_definitions.keys)
29
- @attribute_methods_generated = true
29
+ @@attribute_methods_generated = true
30
30
  end
31
31
 
32
32
  def attribute_methods_generated?
33
- @attribute_methods_generated ||= false
33
+ @@attribute_methods_generated ||= false
34
34
  end
35
35
  end
36
36
 
@@ -79,7 +79,7 @@ module CassandraObject
79
79
  def attribute(name)
80
80
  read_attribute(name)
81
81
  end
82
-
82
+
83
83
  def attribute=(name, value)
84
84
  write_attribute(name, value)
85
85
  end
@@ -41,4 +41,4 @@ module CassandraObject
41
41
  end
42
42
  end
43
43
  end
44
- end
44
+ end
@@ -22,4 +22,4 @@ module CassandraObject
22
22
  end
23
23
  end
24
24
  end
25
- end
25
+ end
@@ -9,9 +9,12 @@ module CassandraObject
9
9
 
10
10
  %w(array boolean date float integer json string time).each do |type|
11
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
12
+ def #{type}(*args)
13
+ options = args.extract_options!
14
+ args.each do |name|
15
+ attribute(name, options.merge(:type => :#{type}))
16
+ end
17
+ end
15
18
  EOV
16
19
  end
17
20
  end
@@ -22,10 +25,10 @@ module CassandraObject
22
25
  child.attribute_definitions = attribute_definitions.dup
23
26
  end
24
27
 
25
- #
28
+ #
26
29
  # attribute :name, type: :string
27
30
  # attribute :ammo, type: Ammo, coder: AmmoCodec
28
- #
31
+ #
29
32
  def attribute(name, options)
30
33
  type = options[:type]
31
34
  coder = options[:coder]
@@ -53,4 +56,4 @@ module CassandraObject
53
56
  end
54
57
  end
55
58
  end
56
- end
59
+ end
@@ -22,12 +22,20 @@ module CassandraObject
22
22
  end
23
23
  klass
24
24
  end
25
+
26
+ def config=(config)
27
+ @@config = config.is_a?(Hash) ? CassandraObject::Config.new(config) : config
28
+ end
29
+
30
+ def config
31
+ @@config
32
+ end
25
33
  end
26
34
 
27
35
  extend ActiveModel::Naming
28
36
  include ActiveModel::Conversion
29
37
  extend ActiveSupport::DescendantsTracker
30
-
38
+
31
39
  include Connection
32
40
  include Consistency
33
41
  include Identity
@@ -43,50 +51,10 @@ module CassandraObject
43
51
  include Timestamps
44
52
  include Savepoints
45
53
  include Scoping
54
+ include Core
46
55
 
47
56
  include Serialization
48
-
49
- def initialize(attributes=nil)
50
- @new_record = true
51
- @destroyed = false
52
- @attributes = {}
53
- self.attributes = attributes || {}
54
- attribute_definitions.each do |attr, attribute_definition|
55
- unless attribute_exists?(attr)
56
- @attributes[attr.to_s] = self.class.typecast_attribute(self, attr, nil)
57
- end
58
- end
59
- end
60
-
61
- def initialize_dup(other)
62
- @attributes = other.attributes
63
- @attributes['created_at'] = nil
64
- @attributes['updated_at'] = nil
65
- @attributes.delete(self.class.primary_key)
66
- @id = nil
67
- @new_record = true
68
- @destroyed = false
69
- super
70
- end
71
-
72
- def to_param
73
- id
74
- end
75
-
76
- def hash
77
- id.hash
78
- end
79
-
80
- def ==(comparison_object)
81
- comparison_object.equal?(self) ||
82
- (comparison_object.instance_of?(self.class) &&
83
- comparison_object.id == id)
84
- end
85
-
86
- def eql?(comparison_object)
87
- self == (comparison_object)
88
- end
89
57
  end
90
58
  end
91
59
 
92
- ActiveSupport.run_load_hooks(:cassandra_object, CassandraObject::Base)
60
+ ActiveSupport.run_load_hooks(:cassandra_object, CassandraObject::Base)
@@ -56,4 +56,4 @@ module CassandraObject
56
56
  belongs_to_cache[name.to_sym] = association
57
57
  end
58
58
  end
59
- end
59
+ end
@@ -50,4 +50,4 @@ module CassandraObject
50
50
  end
51
51
  end
52
52
  end
53
- end
53
+ end
@@ -23,8 +23,8 @@ module CassandraObject
23
23
  end
24
24
 
25
25
  def class_name
26
- options[:class_name] || name.to_s.classify
26
+ options[:class_name] || name.to_s.camelize
27
27
  end
28
28
  end
29
29
  end
30
- end
30
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support/core_ext/hash/keys'
2
+
3
+ module CassandraObject
4
+ class Config
5
+ attr_accessor :servers, :keyspace, :thrift_options, :keyspace_options
6
+
7
+ def initialize(options)
8
+ options = options.symbolize_keys
9
+ self.servers = Array.wrap(options[:servers] || "127.0.0.1:9160")
10
+ self.keyspace = options[:keyspace]
11
+ self.thrift_options = (options[:thrift] || {}).symbolize_keys
12
+ self.keyspace_options = (options[:keyspace_options] || {}).symbolize_keys
13
+ end
14
+ end
15
+ end
@@ -16,30 +16,12 @@ module CassandraCQL
16
16
  end
17
17
 
18
18
  module CassandraObject
19
- class Config
20
- attr_accessor :servers, :keyspace, :thrift_options
21
-
22
- def initialize(options)
23
- self.servers = Array.wrap(options[:servers] || "127.0.0.1:9160")
24
- self.keyspace = options[:keyspace]
25
- self.thrift_options = (options[:thrift] || {}).symbolize_keys
26
- end
27
- end
28
-
29
19
  module Connection
30
20
  extend ActiveSupport::Concern
31
-
32
- included do
33
- class_attribute :connection_config
34
- end
35
21
 
36
22
  module ClassMethods
37
- def establish_connection(spec)
38
- self.connection_config = Config.new(spec)
39
- end
40
-
41
23
  def cql
42
- @@cql ||= CassandraCQL::Database.new(connection_config.servers, {keyspace: connection_config.keyspace}, connection_config.thrift_options)
24
+ @@cql ||= CassandraCQL::Database.new(config.servers, {keyspace: config.keyspace}, config.thrift_options)
43
25
  end
44
26
 
45
27
  def execute_cql(cql_string, *bind_vars)
@@ -15,4 +15,4 @@ module CassandraObject
15
15
  class_attribute :default_consistency
16
16
  end
17
17
  end
18
- end
18
+ end
@@ -0,0 +1,46 @@
1
+ module CassandraObject
2
+ module Core
3
+ def initialize(attributes=nil)
4
+ @new_record = true
5
+ @destroyed = false
6
+ @attributes = {}
7
+ self.attributes = attributes || {}
8
+ attribute_definitions.each do |attr, attribute_definition|
9
+ unless attribute_exists?(attr)
10
+ @attributes[attr.to_s] = self.class.typecast_attribute(self, attr, nil)
11
+ end
12
+ end
13
+
14
+ yield self if block_given?
15
+ end
16
+
17
+ def initialize_dup(other)
18
+ @attributes = other.attributes
19
+ @attributes['created_at'] = nil
20
+ @attributes['updated_at'] = nil
21
+ @attributes.delete(self.class.primary_key)
22
+ @id = nil
23
+ @new_record = true
24
+ @destroyed = false
25
+ super
26
+ end
27
+
28
+ def to_param
29
+ id
30
+ end
31
+
32
+ def hash
33
+ id.hash
34
+ end
35
+
36
+ def ==(comparison_object)
37
+ comparison_object.equal?(self) ||
38
+ (comparison_object.instance_of?(self.class) &&
39
+ comparison_object.id == id)
40
+ end
41
+
42
+ def eql?(comparison_object)
43
+ self == (comparison_object)
44
+ end
45
+ end
46
+ end
@@ -4,7 +4,7 @@ module CassandraObject
4
4
 
5
5
  class RecordNotSaved < CasssandraObjectError
6
6
  end
7
-
7
+
8
8
  class RecordNotFound < CasssandraObjectError
9
9
  end
10
- end
10
+ end
@@ -6,7 +6,7 @@ module CassandraObject
6
6
  class_attribute :key_generator
7
7
 
8
8
  key do
9
- SimpleUUID::UUID.new.to_guid
9
+ SimpleUUID::UUID.new.to_guid.tr('-','')
10
10
  end
11
11
  end
12
12
 
@@ -11,8 +11,8 @@ module CassandraObject
11
11
  execute_cql "TRUNCATE #{column_family}"
12
12
  end
13
13
 
14
- def create(attributes = {})
15
- new(attributes).tap do |object|
14
+ def create(attributes = {}, &block)
15
+ new(attributes, &block).tap do |object|
16
16
  object.save
17
17
  end
18
18
  end
@@ -20,12 +20,12 @@ module CassandraObject
20
20
  def write(id, attributes)
21
21
  if (encoded = encode_attributes(attributes)).any?
22
22
  insert_attributes = {'KEY' => id}.update encode_attributes(attributes)
23
- statement = "INSERT INTO #{column_family} (#{insert_attributes.keys * ','}) VALUES (#{Array.new(insert_attributes.size, '?') * ','})#{write_option_string}"
23
+ statement = "INSERT INTO #{column_family} (#{quote_columns(insert_attributes.keys) * ','}) VALUES (#{Array.new(insert_attributes.size, '?') * ','})#{write_option_string}"
24
24
  execute_batchable_cql statement, *insert_attributes.values
25
25
  end
26
26
 
27
27
  if (nil_attributes = attributes.select { |key, value| value.nil? }).any?
28
- execute_batchable_cql "DELETE #{nil_attributes.keys * ','} FROM #{column_family}#{write_option_string} WHERE KEY = ?", id
28
+ execute_batchable_cql "DELETE #{quote_columns(nil_attributes.keys) * ','} FROM #{column_family}#{write_option_string} WHERE KEY = ?", id
29
29
  end
30
30
  end
31
31
 
@@ -37,9 +37,9 @@ module CassandraObject
37
37
  return nil unless @batch.any?
38
38
 
39
39
  [
40
- "BEGIN BATCH#{write_option_string(true)}",
41
- @batch * "\n",
42
- 'APPLY BATCH'
40
+ "BEGIN BATCH#{write_option_string(true)}",
41
+ @batch * "\n",
42
+ 'APPLY BATCH'
43
43
  ] * "\n"
44
44
  end
45
45
 
@@ -84,6 +84,11 @@ module CassandraObject
84
84
  end
85
85
 
86
86
  private
87
+
88
+ def quote_columns(column_names)
89
+ column_names.map { |name| "'#{name}'" }
90
+ end
91
+
87
92
  def execute_batchable_cql(cql_string, *bind_vars)
88
93
  if @batch
89
94
  @batch << CassandraCQL::Statement.sanitize(cql_string, bind_vars)
@@ -142,8 +147,17 @@ module CassandraObject
142
147
  save!
143
148
  end
144
149
 
150
+ def becomes(klass)
151
+ became = klass.new
152
+ became.instance_variable_set("@attributes", @attributes)
153
+ became.instance_variable_set("@new_record", new_record?)
154
+ became.instance_variable_set("@destroyed", destroyed?)
155
+ became
156
+ end
157
+
145
158
  def reload
146
159
  @attributes.update(self.class.find(id).instance_variable_get('@attributes'))
160
+ self
147
161
  end
148
162
 
149
163
  private
@@ -4,4 +4,4 @@ module CassandraObject
4
4
  load 'cassandra_object/tasks/ks.rake'
5
5
  end
6
6
  end
7
- end
7
+ end
@@ -73,7 +73,7 @@ module CassandraObject
73
73
 
74
74
  def update
75
75
  self.class.add_savepoint_rollback(:update, self)
76
- super
76
+ super
77
77
  end
78
78
  end
79
79
  end
@@ -5,10 +5,19 @@ module CassandraObject
5
5
  extend Tasks
6
6
 
7
7
  class << self
8
- def create_keyspace(keyspace)
9
- system_execute "CREATE KEYSPACE #{keyspace} " +
10
- "WITH strategy_class = SimpleStrategy " +
11
- " AND strategy_options:replication_factor = 1"
8
+ DEFAULT_CREATE_KEYSPACE = {
9
+ 'strategy_class' => 'SimpleStrategy',
10
+ 'strategy_options:replication_factor' => 1
11
+ }
12
+
13
+ def create_keyspace(keyspace, options = {})
14
+ stmt = "CREATE KEYSPACE #{keyspace}"
15
+
16
+ if options.empty?
17
+ options = DEFAULT_CREATE_KEYSPACE
18
+ end
19
+
20
+ system_execute statement_with_options(stmt, options)
12
21
  end
13
22
 
14
23
  def drop_keyspace(keyspace)
@@ -19,30 +28,36 @@ module CassandraObject
19
28
  stmt = "CREATE COLUMNFAMILY #{column_family} " +
20
29
  "(KEY varchar PRIMARY KEY)"
21
30
 
22
- if options.any?
23
- with_stmt = options.map do |k,v|
24
- "#{k} = #{CassandraCQL::Statement.quote(v)}"
25
- end.join(' AND ')
26
- stmt << " WITH #{with_stmt}"
27
- end
28
-
29
- execute stmt
31
+ execute statement_with_options(stmt, options)
30
32
  end
31
33
 
32
- def alter_column_family_with(with)
33
- execute "ALTER TABLE users WITH #{with}"
34
+ def alter_column_family(column_family, options)
35
+ stmt = "ALTER TABLE #{column_family}"
36
+ execute statement_with_options(stmt, options)
34
37
  end
35
38
 
36
39
  def add_index()
37
40
  end
38
41
 
39
42
  private
43
+ def statement_with_options(stmt, options)
44
+ if options.any?
45
+ with_stmt = options.map do |k,v|
46
+ "#{k} = #{CassandraCQL::Statement.quote(v)}"
47
+ end.join(' AND ')
48
+
49
+ stmt << " WITH #{with_stmt}"
50
+ end
51
+
52
+ stmt
53
+ end
54
+
40
55
  def execute(cql)
41
56
  CassandraObject::Base.execute_cql cql
42
57
  end
43
58
 
44
59
  def system_execute(cql)
45
- @system_cql ||= CassandraCQL::Database.new(CassandraObject::Base.connection_config.servers, keyspace: 'system')
60
+ @system_cql ||= CassandraCQL::Database.new(CassandraObject::Base.config.servers, keyspace: 'system')
46
61
  @system_cql.execute cql
47
62
  end
48
63
  end