sessionm-cassandra_object 2.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/.gitignore +2 -0
  2. data/CHANGELOG +3 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +13 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.markdown +12 -0
  7. data/Rakefile +15 -0
  8. data/lib/cassandra_object/associations/one_to_many.rb +146 -0
  9. data/lib/cassandra_object/associations/one_to_one.rb +85 -0
  10. data/lib/cassandra_object/associations.rb +50 -0
  11. data/lib/cassandra_object/attributes.rb +97 -0
  12. data/lib/cassandra_object/base.rb +97 -0
  13. data/lib/cassandra_object/batches.rb +31 -0
  14. data/lib/cassandra_object/callbacks.rb +27 -0
  15. data/lib/cassandra_object/collection.rb +8 -0
  16. data/lib/cassandra_object/connection.rb +29 -0
  17. data/lib/cassandra_object/consistency.rb +31 -0
  18. data/lib/cassandra_object/cursor.rb +90 -0
  19. data/lib/cassandra_object/dirty.rb +32 -0
  20. data/lib/cassandra_object/errors.rb +10 -0
  21. data/lib/cassandra_object/finder_methods.rb +72 -0
  22. data/lib/cassandra_object/generators/migration_generator.rb +31 -0
  23. data/lib/cassandra_object/generators/templates/migration.rb.erb +11 -0
  24. data/lib/cassandra_object/identity/abstract_key_factory.rb +36 -0
  25. data/lib/cassandra_object/identity/custom_key_factory.rb +50 -0
  26. data/lib/cassandra_object/identity/hashed_natural_key_factory.rb +10 -0
  27. data/lib/cassandra_object/identity/key.rb +20 -0
  28. data/lib/cassandra_object/identity/natural_key_factory.rb +51 -0
  29. data/lib/cassandra_object/identity/uuid_key_factory.rb +39 -0
  30. data/lib/cassandra_object/identity.rb +52 -0
  31. data/lib/cassandra_object/log_subscriber.rb +37 -0
  32. data/lib/cassandra_object/migrations/migration.rb +15 -0
  33. data/lib/cassandra_object/migrations.rb +66 -0
  34. data/lib/cassandra_object/mocking.rb +15 -0
  35. data/lib/cassandra_object/persistence.rb +138 -0
  36. data/lib/cassandra_object/railtie.rb +11 -0
  37. data/lib/cassandra_object/schema/migration.rb +106 -0
  38. data/lib/cassandra_object/schema/migration_proxy.rb +25 -0
  39. data/lib/cassandra_object/schema/migrator.rb +213 -0
  40. data/lib/cassandra_object/schema.rb +37 -0
  41. data/lib/cassandra_object/serialization.rb +6 -0
  42. data/lib/cassandra_object/tasks/column_family.rb +90 -0
  43. data/lib/cassandra_object/tasks/keyspace.rb +89 -0
  44. data/lib/cassandra_object/tasks/ks.rake +121 -0
  45. data/lib/cassandra_object/timestamps.rb +19 -0
  46. data/lib/cassandra_object/type.rb +19 -0
  47. data/lib/cassandra_object/types/array_type.rb +16 -0
  48. data/lib/cassandra_object/types/boolean_type.rb +23 -0
  49. data/lib/cassandra_object/types/date_type.rb +20 -0
  50. data/lib/cassandra_object/types/float_type.rb +19 -0
  51. data/lib/cassandra_object/types/hash_type.rb +16 -0
  52. data/lib/cassandra_object/types/integer_type.rb +19 -0
  53. data/lib/cassandra_object/types/set_type.rb +22 -0
  54. data/lib/cassandra_object/types/string_type.rb +16 -0
  55. data/lib/cassandra_object/types/time_type.rb +27 -0
  56. data/lib/cassandra_object/types/time_with_zone_type.rb +18 -0
  57. data/lib/cassandra_object/types/utf8_string_type.rb +18 -0
  58. data/lib/cassandra_object/types.rb +11 -0
  59. data/lib/cassandra_object/validations.rb +46 -0
  60. data/lib/cassandra_object.rb +49 -0
  61. data/sessionm-cassandra_object.gemspec +26 -0
  62. data/test/active_model_test.rb +9 -0
  63. data/test/base_test.rb +28 -0
  64. data/test/batches_test.rb +30 -0
  65. data/test/connection_test.rb +28 -0
  66. data/test/consistency_test.rb +20 -0
  67. data/test/finder_methods_test.rb +49 -0
  68. data/test/identity_test.rb +30 -0
  69. data/test/persistence_test.rb +84 -0
  70. data/test/test_helper.rb +31 -0
  71. data/test/timestamps_test.rb +27 -0
  72. data/test/types/array_type_test.rb +15 -0
  73. data/test/types/boolean_type_test.rb +23 -0
  74. data/test/types/date_type_test.rb +4 -0
  75. data/test/types/float_type_test.rb +4 -0
  76. data/test/types/hash_type_test.rb +4 -0
  77. data/test/types/integer_type_test.rb +18 -0
  78. data/test/types/set_type_test.rb +17 -0
  79. data/test/types/string_type_test.rb +4 -0
  80. data/test/types/time_type_test.rb +4 -0
  81. data/test/types/utf8_string_type_test.rb +4 -0
  82. data/test/validations_test.rb +15 -0
  83. metadata +183 -0
@@ -0,0 +1,89 @@
1
+ module CassandraObject
2
+
3
+ module Tasks
4
+
5
+ class Keyspace
6
+
7
+ def self.parse(hash)
8
+ ks = Cassandra::Keyspace.new.with_fields hash
9
+ ks.cf_defs = []
10
+ hash['cf_defs'].each do |cf|
11
+ ks.cf_defs << Cassandra::ColumnFamily.new.with_fields(cf)
12
+ end
13
+ ks
14
+ end
15
+
16
+ def exists?(name)
17
+ connection.keyspaces.include? name.to_s
18
+ end
19
+
20
+ def create(name, options = {})
21
+ opts = { :name => name.to_s,
22
+ :strategy_class => 'org.apache.cassandra.locator.LocalStrategy',
23
+ :replication_factor => 1,
24
+ :cf_defs => [] }.merge(options)
25
+
26
+ ks = Cassandra::Keyspace.new.with_fields(opts)
27
+ connection.add_keyspace ks
28
+ end
29
+
30
+ def drop(name)
31
+ connection.drop_keyspace name.to_s
32
+ end
33
+
34
+ def set(name)
35
+ connection.keyspace = name.to_s
36
+ end
37
+
38
+ def get
39
+ connection.keyspace
40
+ end
41
+
42
+ def clear
43
+ return puts 'Cannot clear system keyspace' if connection.keyspace == 'system'
44
+
45
+ connection.clear_keyspace!
46
+ end
47
+
48
+ def schema_dump
49
+ connection.schema
50
+ end
51
+
52
+ def schema_load(schema)
53
+ connection.schema.cf_defs.each do |cf|
54
+ connection.drop_column_family cf.name
55
+ end
56
+
57
+ keyspace = get
58
+ schema.cf_defs.each do |cf|
59
+ cf.keyspace = keyspace
60
+ connection.add_column_family cf
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def connection
67
+ unless @connection
68
+ c = CassandraObject::Base.connection
69
+ @connection = Cassandra.new('system', c.servers, c.thrift_client_options)
70
+ end
71
+ @connection
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+
80
+ class Cassandra
81
+ class Keyspace
82
+ def with_fields(options)
83
+ struct_fields.collect { |f| f[1][:name] }.each do |f|
84
+ send("#{f}=", options[f.to_sym] || options[f.to_s])
85
+ end
86
+ self
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,121 @@
1
+ namespace :ks do
2
+ task :configure => :environment do
3
+ @configs = YAML.load_file(Rails.root.join("config", "cassandra.yml"))
4
+ @config = @configs[Rails.env || 'development']
5
+ end
6
+
7
+ #task :set_keyspace => :configure do
8
+ #set_keyspace
9
+ #end
10
+
11
+ desc 'Create the keyspace in config/cassandra.yml for the current environment'
12
+ task :create => :configure do
13
+ CassandraObject::Tasks::Keyspace.new.create @config['keyspace'], @config
14
+ puts "Created keyspace: #{@config['keyspace']}"
15
+ end
16
+
17
+ namespace :create do
18
+ desc 'Create keyspaces in config/cassandra.yml for all environments'
19
+ task :all => :configure do
20
+ created = []
21
+ @configs.values.each do |config|
22
+ CassandraObject::Tasks::Keyspace.new.create config['keyspace'], config
23
+ created << config['keyspace']
24
+ end
25
+ puts "Created keyspaces: #{created.join(', ')}"
26
+ end
27
+ end
28
+
29
+ desc 'Drop keyspace in config/cassandra.yml for the current environment'
30
+ task :drop => :configure do
31
+ CassandraObject::Tasks::Keyspace.new.drop @config['keyspace']
32
+ puts "Dropped keyspace: #{@config['keyspace']}"
33
+ end
34
+
35
+ namespace :drop do
36
+ desc 'Drop keyspaces in config/cassandra.yml for all environments'
37
+ task :all => :configure do
38
+ dropped = []
39
+ @configs.values.each do |config|
40
+ CassandraObject::Tasks::Keyspace.new.drop config['keyspace']
41
+ dropped << config['keyspace']
42
+ end
43
+ puts "Dropped keyspaces: #{dropped.join(', ')}"
44
+ end
45
+ end
46
+
47
+ desc 'Migrate the keyspace (options: VERSION=x)'
48
+ task :migrate => :configure do
49
+ version = ( ENV['VERSION'] ? ENV['VERSION'].to_i : nil )
50
+ CassandraObject::Schema::Migrator.migrate CassandraObject::Schema::Migrator.migrations_path, version
51
+ schema_dump
52
+ end
53
+
54
+ desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n)'
55
+ task :rollback => :set_keyspace do
56
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
57
+ CassandraObject::Schema::Migrator.rollback CassandraObject::Schema::Migrator.migrations_path, step
58
+ schema_dump
59
+ end
60
+
61
+ desc 'Pushes the schema to the next version (specify steps w/ STEP=n)'
62
+ task :forward => :set_keyspace do
63
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
64
+ CassandraObject::Schema::Migrator.forward CassandraObject::Schema::Migrator.migrations_path, step
65
+ schema_dump
66
+ end
67
+
68
+ namespace :schema do
69
+ desc 'Create ks/schema.json file that can be portably used against any Cassandra instance supported by CassandraObject'
70
+ task :dump => :configure do
71
+ schema_dump
72
+ end
73
+
74
+ desc 'Load ks/schema.json file into Cassandra'
75
+ task :load => :configure do
76
+ schema_load
77
+ end
78
+ end
79
+
80
+ namespace :test do
81
+ desc 'Load the development schema in to the test keyspace'
82
+ task :prepare => :configure do
83
+ schema_dump :development
84
+ schema_load :test
85
+ end
86
+ end
87
+
88
+ desc 'Retrieves the current schema version number'
89
+ task :version => :set_keyspace do
90
+ version = CassandraObject::Schema::Migrator.current_version
91
+ puts "Current version: #{version}"
92
+ end
93
+
94
+ private
95
+
96
+ def schema_dump(env = Rails.env)
97
+ ks = set_keyspace env
98
+ File.open "#{Rails.root}/ks/schema.json", 'w' do |file|
99
+ schema = ActiveSupport::JSON.decode(ks.schema_dump.to_json)
100
+ JSON.pretty_generate(schema).split(/\n/).each do |line|
101
+ file.puts line
102
+ end
103
+ end
104
+ end
105
+
106
+ def schema_load(env = Rails.env)
107
+ ks = set_keyspace env
108
+ File.open "#{Rails.root}/ks/schema.json", 'r' do |file|
109
+ hash = JSON.parse(file.read(nil))
110
+ ks.schema_load CassandraObject::Tasks::Keyspace.parse(hash)
111
+ end
112
+ end
113
+
114
+ def set_keyspace(env = Rails.env)
115
+ config = @configs[env.to_s || 'development']
116
+ ks = CassandraObject::Tasks::Keyspace.new
117
+ ks.set config['keyspace']
118
+ ks
119
+ end
120
+ end
121
+
@@ -0,0 +1,19 @@
1
+ module CassandraObject
2
+ module Timestamps
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :created_at, type: :time#_with_zone
7
+ attribute :updated_at, type: :time#_with_zone
8
+
9
+ before_create do #|r|
10
+ self.created_at ||= Time.current
11
+ self.updated_at ||= Time.current
12
+ end
13
+
14
+ before_update if: :changed? do #|r|
15
+ self.updated_at = Time.current
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module CassandraObject
2
+ class Type
3
+ class TypeMapping < Struct.new(:expected_type, :converter)
4
+ end
5
+
6
+ cattr_accessor :attribute_types
7
+ self.attribute_types = {}.with_indifferent_access
8
+
9
+ class << self
10
+ def register(name, expected_type, converter)
11
+ attribute_types[name] = TypeMapping.new(expected_type, converter)
12
+ end
13
+
14
+ def get_mapping(name)
15
+ attribute_types[name]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module CassandraObject
2
+ module Types
3
+ module ArrayType
4
+ def encode(array)
5
+ raise ArgumentError.new("#{self} requires an Array") unless array.kind_of?(Array)
6
+ array.to_json
7
+ end
8
+ module_function :encode
9
+
10
+ def decode(str)
11
+ ActiveSupport::JSON.decode(str)
12
+ end
13
+ module_function :decode
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module CassandraObject
2
+ module Types
3
+ module BooleanType
4
+ TRUE_VALS = [true, 'true', '1']
5
+ FALSE_VALS = [false, 'false', '0', '', nil]
6
+ VALID_VALS = TRUE_VALS + FALSE_VALS
7
+
8
+ def encode(bool)
9
+ unless VALID_VALS.include?(bool)
10
+ raise ArgumentError.new("#{self} requires a boolean")
11
+ end
12
+ TRUE_VALS.include?(bool) ? '1' : '0'
13
+ end
14
+ module_function :encode
15
+
16
+ def decode(str)
17
+ raise ArgumentError.new("Cannot convert #{str} into a boolean") unless VALID_VALS.include?(str)
18
+ TRUE_VALS.include?(str)
19
+ end
20
+ module_function :decode
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module CassandraObject
2
+ module Types
3
+ module DateType
4
+ FORMAT = '%Y-%m-%d'
5
+ REGEX = /\A\d{4}-\d{2}-\d{2}\Z/
6
+ def encode(date)
7
+ raise ArgumentError.new("#{self} requires a Date") unless date.kind_of?(Date)
8
+ date.strftime(FORMAT)
9
+ end
10
+ module_function :encode
11
+
12
+ def decode(str)
13
+ return nil if str.empty?
14
+ raise ArgumentError.new("Cannot convert #{str} into a Date") unless str.kind_of?(String) && str.match(REGEX)
15
+ Date.strptime(str, FORMAT)
16
+ end
17
+ module_function :decode
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module CassandraObject
2
+ module Types
3
+ module FloatType
4
+ REGEX = /\A[-+]?\d+(\.\d+)?\Z/
5
+ def encode(float)
6
+ raise ArgumentError.new("#{self} requires a Float") unless float.kind_of?(Float)
7
+ float.to_s
8
+ end
9
+ module_function :encode
10
+
11
+ def decode(str)
12
+ return nil if str.empty?
13
+ raise ArgumentError.new("Cannot convert #{str} into a Float") unless str.kind_of?(String) && str.match(REGEX)
14
+ str.to_f
15
+ end
16
+ module_function :decode
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module CassandraObject
2
+ module Types
3
+ module HashType
4
+ def encode(hash)
5
+ raise ArgumentError.new("#{self} requires a Hash") unless hash.kind_of?(Hash)
6
+ ActiveSupport::JSON.encode(hash)
7
+ end
8
+ module_function :encode
9
+
10
+ def decode(str)
11
+ ActiveSupport::JSON.decode(str)
12
+ end
13
+ module_function :decode
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module CassandraObject
2
+ module Types
3
+ module IntegerType
4
+ REGEX = /\A[-+]?\d+\Z/
5
+ def encode(int)
6
+ raise ArgumentError.new("#{self} requires an Integer. You passed #{int.inspect}") unless int.kind_of?(Integer)
7
+ int.to_s
8
+ end
9
+ module_function :encode
10
+
11
+ def decode(str)
12
+ return nil if str.empty?
13
+ raise ArgumentError.new("Cannot convert #{str} into an Integer") unless str.kind_of?(String) && str.match(REGEX)
14
+ str.to_i
15
+ end
16
+ module_function :decode
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ module CassandraObject
2
+ module Types
3
+ module SetType
4
+ def encode(set)
5
+ if set.kind_of?(Set)
6
+ set.to_json
7
+ elsif set.kind_of?(Array)
8
+ set.uniq.to_json
9
+ else
10
+ raise ArgumentError.new("#{self} requires an Array or Set")
11
+ end
12
+ end
13
+ module_function :encode
14
+
15
+ def decode(str)
16
+ return str.to_a if str.kind_of?(Set)
17
+ ActiveSupport::JSON.decode(str)
18
+ end
19
+ module_function :decode
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ module CassandraObject
2
+ module Types
3
+ module StringType
4
+ def encode(str)
5
+ raise ArgumentError.new("#{self} requires a String") unless str.kind_of?(String)
6
+ str.dup
7
+ end
8
+ module_function :encode
9
+
10
+ def decode(str)
11
+ str
12
+ end
13
+ module_function :decode
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ module CassandraObject
2
+ module Types
3
+ module TimeType
4
+ # lifted from the implementation of Time.xmlschema and simplified
5
+ REGEX = /\A\s*
6
+ (-?\d+)-(\d\d)-(\d\d)
7
+ T
8
+ (\d\d):(\d\d):(\d\d)
9
+ (\.\d*)?
10
+ (Z|[+-]\d\d:\d\d)?
11
+ \s*\z/ix
12
+
13
+ def encode(time)
14
+ raise ArgumentError.new("#{self} requires a Time") unless time.kind_of?(Time)
15
+ time.xmlschema(6)
16
+ end
17
+ module_function :encode
18
+
19
+ def decode(str)
20
+ return nil if str.empty?
21
+ raise ArgumentError.new("Cannot convert #{str} into a Time") unless str.kind_of?(String) && str.match(REGEX)
22
+ Time.xmlschema(str)
23
+ end
24
+ module_function :decode
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ module CassandraObject
2
+ module Types
3
+ module TimeWithZoneType
4
+ def encode(time)
5
+ raise ArgumentError.new("#{self} requires a Time") unless time.kind_of?(Time)
6
+ time.utc.xmlschema(6)
7
+ end
8
+ module_function :encode
9
+
10
+ def decode(str)
11
+ return nil if str.empty?
12
+ raise ArgumentError.new("Cannot convert #{str} into a Time") unless str.kind_of?(String) && str.match(TimeType::REGEX)
13
+ Time.xmlschema(str).in_time_zone
14
+ end
15
+ module_function :decode
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module CassandraObject
2
+ module Types
3
+ module UTF8StringType
4
+ def encode(str)
5
+ # This is technically the most correct, but it is a pain to require utf-8 encoding for all strings. Should revisit.
6
+ #raise ArgumentError.new("#{self} requires a UTF-8 encoded String") unless str.kind_of?(String) && str.encoding == Encoding::UTF_8
7
+ raise ArgumentError.new("#{self} requires a String") unless str.kind_of?(String)
8
+ str.dup
9
+ end
10
+ module_function :encode
11
+
12
+ def decode(str)
13
+ str.force_encoding('UTF-8')
14
+ end
15
+ module_function :decode
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ CassandraObject::Type.register(:array, Array, CassandraObject::Types::ArrayType)
2
+ CassandraObject::Type.register(:boolean, Object, CassandraObject::Types::BooleanType)
3
+ CassandraObject::Type.register(:date, Date, CassandraObject::Types::DateType)
4
+ CassandraObject::Type.register(:float, Float, CassandraObject::Types::FloatType)
5
+ CassandraObject::Type.register(:hash, Hash, CassandraObject::Types::HashType)
6
+ CassandraObject::Type.register(:integer, Integer, CassandraObject::Types::IntegerType)
7
+ CassandraObject::Type.register(:set, Array, CassandraObject::Types::SetType)
8
+ CassandraObject::Type.register(:time, Time, CassandraObject::Types::TimeType)
9
+ CassandraObject::Type.register(:time_with_zone, ActiveSupport::TimeWithZone, CassandraObject::Types::TimeWithZoneType)
10
+ CassandraObject::Type.register(:string, String, CassandraObject::Types::UTF8StringType) #This could be changed to StringType to support non-utf8 strings
11
+ CassandraObject::Type.register(:utf8, String, CassandraObject::Types::UTF8StringType)
@@ -0,0 +1,46 @@
1
+ module CassandraObject
2
+ class RecordInvalid < StandardError
3
+ attr_reader :record
4
+ def initialize(record)
5
+ @record = record
6
+ super("Invalid record: #{@record.errors.full_messages.to_sentence}")
7
+ end
8
+ end
9
+
10
+ module Validations
11
+ extend ActiveSupport::Concern
12
+ include ActiveModel::Validations
13
+
14
+ included do
15
+ define_model_callbacks :validation
16
+ define_callbacks :validate, :scope => :name
17
+ end
18
+
19
+ module ClassMethods
20
+ def create!(attributes = {})
21
+ new(attributes).tap do |object|
22
+ object.save!
23
+ end
24
+ end
25
+ end
26
+
27
+ def valid?
28
+ run_callbacks :validation do
29
+ super
30
+ end
31
+ end
32
+
33
+ def save(options={})
34
+ perform_validations(options) ? super : false
35
+ end
36
+
37
+ def save!
38
+ save || raise(RecordInvalid.new(self))
39
+ end
40
+
41
+ protected
42
+ def perform_validations(options={})
43
+ (options[:validate] != false) ? valid? : true
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,49 @@
1
+ require 'rails/all'
2
+
3
+ module CassandraObject
4
+ extend ActiveSupport::Autoload
5
+
6
+ autoload :Base
7
+ autoload :Connection
8
+ autoload :Attributes
9
+ autoload :Dirty
10
+ autoload :Consistency
11
+ autoload :Persistence
12
+ autoload :Callbacks
13
+ autoload :Validations
14
+ autoload :Identity
15
+ autoload :Serialization
16
+ autoload :Associations
17
+ autoload :Migrations
18
+ autoload :Cursor
19
+ autoload :Collection
20
+ autoload :Mocking
21
+ autoload :Batches
22
+ autoload :FinderMethods
23
+ autoload :Timestamps
24
+ autoload :Type
25
+ autoload :Schema
26
+
27
+ module Tasks
28
+ extend ActiveSupport::Autoload
29
+ autoload :Keyspace
30
+ autoload :ColumnFamily
31
+ end
32
+
33
+ module Types
34
+ extend ActiveSupport::Autoload
35
+
36
+ autoload :ArrayType
37
+ autoload :BooleanType
38
+ autoload :DateType
39
+ autoload :FloatType
40
+ autoload :HashType
41
+ autoload :IntegerType
42
+ autoload :SetType
43
+ autoload :TimeType
44
+ autoload :TimeWithZoneType
45
+ autoload :UTF8StringType
46
+ end
47
+ end
48
+
49
+ require 'cassandra_object/railtie'
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'sessionm-cassandra_object'
5
+ s.version = '2.2.6'
6
+ s.description = 'Cassandra ActiveModel'
7
+ s.summary = 'Cassandra ActiveModel'
8
+
9
+ s.required_ruby_version = '>= 1.9.2'
10
+ s.required_rubygems_version = '>= 1.3.5'
11
+
12
+ s.authors = ["Michael Koziarski", "gotime", "sessionm"]
13
+ s.email = 'klange@sessionm.com'
14
+ s.homepage = 'http://github.com/sessionm/cassandra_object'
15
+
16
+ s.extra_rdoc_files = ["README.markdown"]
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.require_paths = ['lib']
20
+
21
+ s.add_runtime_dependency('rails', "~> 3.0")
22
+ s.add_runtime_dependency('cassandra', "~> 0.11.3")
23
+
24
+ s.add_development_dependency('bundler', "~> 1.0.0")
25
+ end
26
+
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+
3
+ class ActiveModelTest < CassandraObject::TestCase
4
+ include ActiveModel::Lint::Tests
5
+
6
+ def setup
7
+ @model = Issue.new
8
+ end
9
+ end
data/test/base_test.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::BaseTest < CassandraObject::TestCase
4
+ class Son < CassandraObject::Base
5
+ end
6
+
7
+ class Grandson < Son
8
+ end
9
+
10
+ test 'base_class' do
11
+ assert_equal Son, Son.base_class
12
+ assert_equal Son, Grandson.base_class
13
+ end
14
+
15
+ test 'column family' do
16
+ assert_equal 'CassandraObject::BaseTest::Sons', Son.column_family
17
+ end
18
+
19
+ test 'to_param' do
20
+ issue = Issue.create
21
+ assert_equal issue.id, issue.to_param
22
+ end
23
+
24
+ test 'hash' do
25
+ issue = Issue.create
26
+ assert_equal issue.id.hash, issue.hash
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ class CassandraObject::BatchesTest < CassandraObject::TestCase
4
+ test 'find_each' do
5
+ Issue.create
6
+ Issue.create
7
+
8
+ issues = []
9
+ Issue.find_each do |issue|
10
+ issues << issue
11
+ end
12
+
13
+ assert_equal Issue.all.to_set, issues.to_set
14
+ end
15
+
16
+ test 'find_in_batches' do
17
+ Issue.create
18
+ Issue.create
19
+ Issue.create
20
+
21
+ issue_batches = []
22
+ Issue.find_in_batches(batch_size: 2) do |issues|
23
+ issue_batches << issues
24
+ end
25
+
26
+ assert_equal 2, issue_batches.size
27
+ assert issue_batches.any? { |issues| issues.size == 2 }
28
+ assert issue_batches.any? { |issues| issues.size == 1 }
29
+ end
30
+ end