extendi-cassandra_object 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.travis.yml +23 -0
- data/CHANGELOG +0 -0
- data/Gemfile +17 -0
- data/LICENSE +13 -0
- data/MIT-LICENSE +20 -0
- data/README.md +177 -0
- data/Rakefile +12 -0
- data/extendi-cassandra_object.gemspec +26 -0
- data/lib/cassandra_object.rb +73 -0
- data/lib/cassandra_object/adapters/abstract_adapter.rb +61 -0
- data/lib/cassandra_object/adapters/cassandra_adapter.rb +269 -0
- data/lib/cassandra_object/adapters/cassandra_schemaless_adapter.rb +306 -0
- data/lib/cassandra_object/attribute_methods.rb +96 -0
- data/lib/cassandra_object/attribute_methods/definition.rb +22 -0
- data/lib/cassandra_object/attribute_methods/dirty.rb +36 -0
- data/lib/cassandra_object/attribute_methods/primary_key.rb +25 -0
- data/lib/cassandra_object/attribute_methods/typecasting.rb +59 -0
- data/lib/cassandra_object/base.rb +33 -0
- data/lib/cassandra_object/base_schema.rb +11 -0
- data/lib/cassandra_object/base_schemaless.rb +11 -0
- data/lib/cassandra_object/base_schemaless_dynamic.rb +11 -0
- data/lib/cassandra_object/belongs_to.rb +63 -0
- data/lib/cassandra_object/belongs_to/association.rb +49 -0
- data/lib/cassandra_object/belongs_to/builder.rb +40 -0
- data/lib/cassandra_object/belongs_to/reflection.rb +30 -0
- data/lib/cassandra_object/callbacks.rb +29 -0
- data/lib/cassandra_object/core.rb +63 -0
- data/lib/cassandra_object/errors.rb +10 -0
- data/lib/cassandra_object/identity.rb +26 -0
- data/lib/cassandra_object/inspect.rb +25 -0
- data/lib/cassandra_object/log_subscriber.rb +44 -0
- data/lib/cassandra_object/model.rb +60 -0
- data/lib/cassandra_object/persistence.rb +203 -0
- data/lib/cassandra_object/railtie.rb +33 -0
- data/lib/cassandra_object/railties/controller_runtime.rb +45 -0
- data/lib/cassandra_object/schema.rb +83 -0
- data/lib/cassandra_object/schemaless.rb +83 -0
- data/lib/cassandra_object/scope.rb +86 -0
- data/lib/cassandra_object/scope/finder_methods.rb +54 -0
- data/lib/cassandra_object/scope/query_methods.rb +69 -0
- data/lib/cassandra_object/scoping.rb +27 -0
- data/lib/cassandra_object/serialization.rb +6 -0
- data/lib/cassandra_object/tasks/ks.rake +54 -0
- data/lib/cassandra_object/timestamps.rb +19 -0
- data/lib/cassandra_object/type.rb +16 -0
- data/lib/cassandra_object/types.rb +8 -0
- data/lib/cassandra_object/types/array_type.rb +16 -0
- data/lib/cassandra_object/types/base_type.rb +26 -0
- data/lib/cassandra_object/types/boolean_type.rb +20 -0
- data/lib/cassandra_object/types/date_type.rb +22 -0
- data/lib/cassandra_object/types/float_type.rb +16 -0
- data/lib/cassandra_object/types/integer_type.rb +20 -0
- data/lib/cassandra_object/types/json_type.rb +13 -0
- data/lib/cassandra_object/types/string_type.rb +19 -0
- data/lib/cassandra_object/types/time_type.rb +16 -0
- data/lib/cassandra_object/types/type_helper.rb +39 -0
- data/lib/cassandra_object/validations.rb +44 -0
- data/test/support/cassandra.rb +63 -0
- data/test/support/issue.rb +12 -0
- data/test/support/issue_dynamic.rb +12 -0
- data/test/support/issue_schema.rb +17 -0
- data/test/support/issue_schema_child.rb +17 -0
- data/test/support/issue_schema_father.rb +13 -0
- data/test/test_helper.rb +41 -0
- data/test/unit/active_model_test.rb +18 -0
- data/test/unit/adapters/adapter_test.rb +6 -0
- data/test/unit/attribute_methods/definition_test.rb +13 -0
- data/test/unit/attribute_methods/dirty_test.rb +72 -0
- data/test/unit/attribute_methods/primary_key_test.rb +26 -0
- data/test/unit/attribute_methods/typecasting_test.rb +119 -0
- data/test/unit/attribute_methods_test.rb +51 -0
- data/test/unit/base_test.rb +20 -0
- data/test/unit/belongs_to/reflection_test.rb +12 -0
- data/test/unit/belongs_to_test.rb +63 -0
- data/test/unit/callbacks_test.rb +46 -0
- data/test/unit/connection_test.rb +6 -0
- data/test/unit/connections/connections_test.rb +55 -0
- data/test/unit/core_test.rb +55 -0
- data/test/unit/identity_test.rb +26 -0
- data/test/unit/inspect_test.rb +26 -0
- data/test/unit/log_subscriber_test.rb +25 -0
- data/test/unit/persistence_schema_test.rb +156 -0
- data/test/unit/persistence_test.rb +266 -0
- data/test/unit/railties/controller_runtime_test.rb +48 -0
- data/test/unit/schema/tasks_test.rb +32 -0
- data/test/unit/schema_test.rb +115 -0
- data/test/unit/schemaless_test.rb +100 -0
- data/test/unit/scope/finder_methods_test.rb +117 -0
- data/test/unit/scope/query_methods_test.rb +32 -0
- data/test/unit/scoping_test.rb +7 -0
- data/test/unit/timestamps_test.rb +27 -0
- data/test/unit/types/array_type_test.rb +17 -0
- data/test/unit/types/base_type_test.rb +19 -0
- data/test/unit/types/boolean_type_test.rb +24 -0
- data/test/unit/types/date_type_test.rb +15 -0
- data/test/unit/types/float_type_test.rb +17 -0
- data/test/unit/types/integer_type_test.rb +19 -0
- data/test/unit/types/json_type_test.rb +23 -0
- data/test/unit/types/string_type_test.rb +25 -0
- data/test/unit/types/time_type_test.rb +14 -0
- data/test/unit/validations_test.rb +27 -0
- metadata +202 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Scoping
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
singleton_class.class_eval do
|
7
|
+
delegate :find, :find_by_id, :find_all_in_batches, :first, to: :scope
|
8
|
+
delegate :select, :where, :where_ids, to: :scope
|
9
|
+
delegate :cql_response, :columns, :limit, :per_page, to: :scope
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def scope
|
15
|
+
self.current_scope ||= Scope.new(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def current_scope
|
19
|
+
Thread.current["#{self}_current_scope"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def current_scope=(new_scope)
|
23
|
+
Thread.current["#{self}_current_scope"] = new_scope
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
ks_namespace = namespace :ks do
|
2
|
+
desc 'Create the keyspace in config/cassandra.yml for the current environment'
|
3
|
+
task create: :environment do
|
4
|
+
begin
|
5
|
+
CassandraObject::Schema.create_keyspace CassandraObject::Base.config[:keyspace], CassandraObject::Base.config[:keyspace_options]
|
6
|
+
rescue Exception => e
|
7
|
+
if e.message =~ /conflicts/
|
8
|
+
p "Keyspace #{CassandraObject::Base.config[:keyspace]} already exists"
|
9
|
+
else
|
10
|
+
raise e
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
task drop: :environment do
|
16
|
+
begin
|
17
|
+
CassandraObject::Schema.drop_keyspace CassandraObject::Base.config[:keyspace]
|
18
|
+
rescue Exception => e
|
19
|
+
if e.message =~ /non existing keyspace/
|
20
|
+
p "Keyspace #{CassandraObject::Base.config[:keyspace]} does not exist"
|
21
|
+
else
|
22
|
+
raise e
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
task reset: [:drop, :setup]
|
28
|
+
|
29
|
+
task setup: [:create, :_load]
|
30
|
+
|
31
|
+
namespace :structure do
|
32
|
+
task dump: :environment do
|
33
|
+
filename = ENV['SCHEMA'] || "#{Rails.root}/ks/structure.cql"
|
34
|
+
File.open(filename, "w:utf-8") do |file|
|
35
|
+
CassandraObject::Schema.dump(file)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
task load: :environment do
|
40
|
+
filename = ENV['SCHEMA'] || "#{Rails.root}/ks/structure.cql"
|
41
|
+
File.open(filename) do |file|
|
42
|
+
CassandraObject::Schema.load(file)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
task :_dump do
|
48
|
+
ks_namespace["structure:dump"].invoke
|
49
|
+
end
|
50
|
+
|
51
|
+
task :_load do
|
52
|
+
ks_namespace["structure:load"].invoke
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Timestamps
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
attribute :created_at, type: :time
|
7
|
+
attribute :updated_at, type: :time
|
8
|
+
|
9
|
+
before_create do
|
10
|
+
self.created_at ||= Time.current
|
11
|
+
self.updated_at ||= Time.current
|
12
|
+
end
|
13
|
+
|
14
|
+
before_update if: :changed? do
|
15
|
+
self.updated_at = Time.current
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
class Type
|
3
|
+
cattr_accessor :attribute_types
|
4
|
+
self.attribute_types = {}.with_indifferent_access
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def register(name, coder)
|
8
|
+
attribute_types[name] = coder
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_coder(name)
|
12
|
+
attribute_types[name]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
CassandraObject::Type.register(:array, CassandraObject::Types::ArrayType)
|
2
|
+
CassandraObject::Type.register(:boolean, CassandraObject::Types::BooleanType)
|
3
|
+
CassandraObject::Type.register(:date, CassandraObject::Types::DateType)
|
4
|
+
CassandraObject::Type.register(:float, CassandraObject::Types::FloatType)
|
5
|
+
CassandraObject::Type.register(:integer, CassandraObject::Types::IntegerType)
|
6
|
+
CassandraObject::Type.register(:json, CassandraObject::Types::JsonType)
|
7
|
+
CassandraObject::Type.register(:time, CassandraObject::Types::TimeType)
|
8
|
+
CassandraObject::Type.register(:string, CassandraObject::Types::StringType)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class ArrayType < BaseType
|
4
|
+
def encode(array)
|
5
|
+
raise ArgumentError.new("#{array.inspect} is not an Array") unless array.kind_of?(Array)
|
6
|
+
array.to_a.to_json
|
7
|
+
end
|
8
|
+
|
9
|
+
def decode(str)
|
10
|
+
return nil if str.blank?
|
11
|
+
|
12
|
+
ActiveSupport::JSON.decode(str)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class BaseType
|
4
|
+
attr_accessor :options
|
5
|
+
def initialize(options = {})
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def default
|
10
|
+
options[:default].duplicable? ? options[:default].dup : options[:default]
|
11
|
+
end
|
12
|
+
|
13
|
+
def encode(value)
|
14
|
+
value.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def decode(str)
|
18
|
+
str
|
19
|
+
end
|
20
|
+
|
21
|
+
def typecast(value)
|
22
|
+
value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class BooleanType < BaseType
|
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("#{bool.inspect} is not a Boolean")
|
11
|
+
end
|
12
|
+
TRUE_VALS.include?(bool) ? '1' : '0'
|
13
|
+
end
|
14
|
+
|
15
|
+
def decode(str)
|
16
|
+
TRUE_VALS.include?(str)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class DateType < BaseType
|
4
|
+
FORMAT = '%Y-%m-%d'
|
5
|
+
REGEX = /\A\d{4}-\d{2}-\d{2}\Z/
|
6
|
+
|
7
|
+
def encode(value)
|
8
|
+
raise ArgumentError.new("#{value.inspect} is not a Date") unless value.kind_of?(Date)
|
9
|
+
value.strftime(FORMAT)
|
10
|
+
end
|
11
|
+
|
12
|
+
def decode(str)
|
13
|
+
return nil if str.empty?
|
14
|
+
Date.parse(str)
|
15
|
+
end
|
16
|
+
|
17
|
+
def typecast(value)
|
18
|
+
value.to_date
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class FloatType < BaseType
|
4
|
+
REGEX = /\A[-+]?\d+(\.\d+)?\Z/
|
5
|
+
def encode(float)
|
6
|
+
raise ArgumentError.new("#{float.inspect} is not a Float") unless float.kind_of?(Float)
|
7
|
+
float.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def decode(str)
|
11
|
+
return nil if str.empty?
|
12
|
+
str.to_f
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class IntegerType < BaseType
|
4
|
+
REGEX = /\A[-+]?\d+\Z/
|
5
|
+
def encode(int)
|
6
|
+
raise ArgumentError.new("#{int.inspect} is not an Integer.") unless int.kind_of?(Integer)
|
7
|
+
int.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def decode(str)
|
11
|
+
return nil if str.empty?
|
12
|
+
str.to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
def typecast(value)
|
16
|
+
value.to_i
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class StringType < BaseType
|
4
|
+
def encode(str)
|
5
|
+
raise ArgumentError.new("#{str.inspect} is not a String") unless str.kind_of?(String)
|
6
|
+
|
7
|
+
unless str.encoding == Encoding::UTF_8
|
8
|
+
(str.frozen? ? str.dup : str).force_encoding('UTF-8')
|
9
|
+
else
|
10
|
+
str
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def typecast(value)
|
15
|
+
value.to_s
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class TimeType < BaseType
|
4
|
+
def encode(time)
|
5
|
+
raise ArgumentError.new("#{time.inspect} is not a Time") unless time.kind_of?(Time)
|
6
|
+
time.utc.xmlschema(6)
|
7
|
+
end
|
8
|
+
|
9
|
+
def decode(str)
|
10
|
+
Time.parse(str).utc.in_time_zone if str
|
11
|
+
rescue
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Types
|
3
|
+
class TypeHelper
|
4
|
+
|
5
|
+
def self.guess_type(object)
|
6
|
+
case object
|
7
|
+
when ::String then Cassandra::Types.varchar
|
8
|
+
when ::Fixnum then Cassandra::Types.int
|
9
|
+
when ::Integer then Cassandra::Types.int
|
10
|
+
when ::Float then Cassandra::Types.float
|
11
|
+
when ::Bignum then Cassandra::Types.varint
|
12
|
+
when ::BigDecimal then Cassandra::Types.decimal
|
13
|
+
when ::TrueClass then Cassandra::Types.boolean
|
14
|
+
when ::FalseClass then Cassandra::Types.boolean
|
15
|
+
when ::NilClass then Cassandra::Types.bigint
|
16
|
+
# when Uuid then Cassandra::Types.uuid
|
17
|
+
# when TimeUuid then Cassandra::Types.timeuuid
|
18
|
+
when ::IPAddr then Cassandra::Types.inet
|
19
|
+
when ::Time then Cassandra::Types.timestamp
|
20
|
+
when ::Hash
|
21
|
+
pair = object.first
|
22
|
+
Types.map(guess_type(pair[0]), guess_type(pair[1]))
|
23
|
+
when ::Array then Types.list(guess_type(object.first))
|
24
|
+
when ::Set then Types.set(guess_type(object.first))
|
25
|
+
# when Tuple::Strict then Types.tuple(*object.types)
|
26
|
+
# when Tuple then Types.tuple(*object.map {|v| guess_type(v)})
|
27
|
+
# when UDT::Strict
|
28
|
+
# Types.udt(object.keyspace, object.name, object.types)
|
29
|
+
# when UDT
|
30
|
+
# Types.udt('unknown', 'unknown', object.map {|k, v| [k, guess_type(v)]})
|
31
|
+
when Cassandra::CustomData then object.class.type
|
32
|
+
else
|
33
|
+
raise ::ArgumentError, "Unable to guess the type of the argument: #{object.inspect}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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_callbacks :validate, scope: :name
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
def create!(attributes = {})
|
20
|
+
new(attributes).tap do |object|
|
21
|
+
object.save!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def save(options={})
|
27
|
+
if perform_validations(options)
|
28
|
+
super
|
29
|
+
true
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def save!
|
36
|
+
save || raise(RecordInvalid.new(self))
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def perform_validations(options={})
|
41
|
+
(options[:validate] != false) ? valid? : true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
Bundler.require :cassandra
|
2
|
+
|
3
|
+
CassandraObject::Base.config = {
|
4
|
+
keyspace: 'cassandra_object_test',
|
5
|
+
hosts: ['127.0.0.1'],
|
6
|
+
compression: :lz4,
|
7
|
+
connect_timeout: 1,
|
8
|
+
timeout: 30,
|
9
|
+
consistency: :quorum,
|
10
|
+
protocol_version: 3,
|
11
|
+
page_size: 10000,
|
12
|
+
trace: true,
|
13
|
+
connections_per_local_node: 4,
|
14
|
+
schema_refresh_delay: 0.1,
|
15
|
+
schema_refresh_timeout: 0.1,
|
16
|
+
# connections_per_remote_node: nil,
|
17
|
+
# logger: Logger.new($stderr)
|
18
|
+
}
|
19
|
+
|
20
|
+
begin
|
21
|
+
CassandraObject::Schema.drop_keyspace 'cassandra_object_test', true
|
22
|
+
CassandraObject::Schema.drop_keyspace 'blah', true
|
23
|
+
rescue Exception => e
|
24
|
+
puts e.message
|
25
|
+
end
|
26
|
+
|
27
|
+
sleep 1
|
28
|
+
CassandraObject::Schema.create_keyspace 'cassandra_object_test'
|
29
|
+
CassandraObject::Schemaless.create_column_family 'Issues'
|
30
|
+
CassandraObject::Schema.create_column_family 'IssueSchemas', {attributes: 'id text, title text, description text, field float, intero int, created_at timestamp, updated_at timestamp, PRIMARY KEY (id)', options: {}}
|
31
|
+
CassandraObject::Schemaless.create_column_family 'IssueDynamics'
|
32
|
+
CassandraObject::Schema.create_column_family 'IssueSchemaFathers', {attributes: 'id text, title text, field float, created_at timestamp, updated_at timestamp, PRIMARY KEY (id)', options: {}}
|
33
|
+
CassandraObject::Schema.create_column_family 'IssueSchemaChildren', {attributes: 'id text, title text, description text, field float, created_at timestamp, updated_at timestamp, issue_schema_father_id text, PRIMARY KEY (id)', options: {}}
|
34
|
+
CassandraObject::BaseSchemaless.adapter.consistency = :quorum
|
35
|
+
CassandraObject::BaseSchemalessDynamic.adapter.consistency = :quorum
|
36
|
+
CassandraObject::BaseSchema.adapter.consistency = :quorum
|
37
|
+
|
38
|
+
CassandraObject::Base.class_eval do
|
39
|
+
class_attribute :created_records
|
40
|
+
self.created_records = []
|
41
|
+
|
42
|
+
after_create do
|
43
|
+
created_records << self
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.delete_after_test
|
47
|
+
# created_records.reject(&:destroyed?).each(&:destroy)
|
48
|
+
Issue.delete_all
|
49
|
+
IssueSchema.delete_all
|
50
|
+
IssueDynamic.delete_all
|
51
|
+
created_records.clear
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module ActiveSupport
|
56
|
+
class TestCase
|
57
|
+
teardown do
|
58
|
+
if CassandraObject::Base.created_records.any?
|
59
|
+
CassandraObject::Base.delete_after_test
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|