gotime-cassandra_object 4.5.1 → 4.6.0

Sign up to get free protection for your applications and to get access to all the features.
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