cequel 1.3.2 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +2 -2
- data/lib/cequel/metal/data_set.rb +1 -0
- data/lib/cequel/metal/keyspace.rb +26 -6
- data/lib/cequel/metal/row.rb +1 -0
- data/lib/cequel/record.rb +12 -0
- data/lib/cequel/record/errors.rb +12 -0
- data/lib/cequel/record/persistence.rb +14 -3
- data/lib/cequel/record/schema.rb +2 -0
- data/lib/cequel/schema/keyspace.rb +5 -0
- data/lib/cequel/schema/migration_validator.rb +2 -1
- data/lib/cequel/spec_support.rb +11 -0
- data/lib/cequel/spec_support/preparation.rb +130 -0
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/metal/keyspace_spec.rb +14 -0
- data/spec/examples/record/list_spec.rb +1 -1
- data/spec/examples/record/map_spec.rb +1 -1
- data/spec/examples/record/persistence_spec.rb +39 -2
- data/spec/examples/record/schema_spec.rb +18 -10
- data/spec/examples/record/set_spec.rb +1 -1
- data/spec/examples/spec_support/preparation_spec.rb +81 -0
- data/spec/support/helpers.rb +1 -2
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94c47d58ecd94cbaf5eb664962dc94aad6fcdfc7
|
4
|
+
data.tar.gz: 7a88e130ad1aec7083a9acf7efcd3d71a736472e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 098e9d6b6e4aafb27140892e5911a65b718c9e869fa975a6d81d690720015c65462e0f59ef1190ea34c30dfca7747a9dac41ea8473edfa8c82666ab39b1a0f7a
|
7
|
+
data.tar.gz: ca9f78e81f43253dcf48215320e7743211e260b179d85a3df92280d886cf12a5d1277364374eb45f7739467f7498953b4dea6c28c809c8fd68a887113c5e4c78
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cequel (1.
|
4
|
+
cequel (1.4.0)
|
5
5
|
activemodel (>= 3.1, < 5.0)
|
6
6
|
cql-rb (>= 1.2, < 3.0)
|
7
7
|
|
@@ -284,7 +284,7 @@ GEM
|
|
284
284
|
thread_safe (0.3.4)
|
285
285
|
thread_safe (0.3.4-java)
|
286
286
|
timecop (0.7.1)
|
287
|
-
tzinfo (1.2.
|
287
|
+
tzinfo (1.2.1)
|
288
288
|
thread_safe (~> 0.1)
|
289
289
|
yard (0.8.7.4)
|
290
290
|
|
@@ -143,7 +143,11 @@ module Cequel
|
|
143
143
|
# @api private
|
144
144
|
#
|
145
145
|
def client
|
146
|
-
synchronize
|
146
|
+
synchronize do
|
147
|
+
@client ||= raw_client.tap do |client|
|
148
|
+
client.use(name) if name
|
149
|
+
end
|
150
|
+
end
|
147
151
|
end
|
148
152
|
|
149
153
|
#
|
@@ -195,6 +199,19 @@ module Cequel
|
|
195
199
|
@default_consistency || :quorum
|
196
200
|
end
|
197
201
|
|
202
|
+
# @return [Boolean] true if the keyspace exists
|
203
|
+
def exists?
|
204
|
+
statement = <<-CQL
|
205
|
+
SELECT keyspace_name
|
206
|
+
FROM system.schema_keyspaces
|
207
|
+
WHERE keyspace_name = ?
|
208
|
+
CQL
|
209
|
+
|
210
|
+
log('CQL', statement, [name]) do
|
211
|
+
raw_client.execute(sanitize(statement, [name])).any?
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
198
215
|
private
|
199
216
|
|
200
217
|
attr_reader :lock
|
@@ -205,12 +222,15 @@ module Cequel
|
|
205
222
|
def_delegator :lock, :synchronize
|
206
223
|
private :lock
|
207
224
|
|
208
|
-
def
|
209
|
-
|
210
|
-
|
225
|
+
def raw_client
|
226
|
+
synchronize do
|
227
|
+
@raw_client ||= Cql::Client.connect(client_options)
|
211
228
|
end
|
212
|
-
|
213
|
-
|
229
|
+
end
|
230
|
+
|
231
|
+
def client_options
|
232
|
+
{hosts: hosts, port: port}.tap do |options|
|
233
|
+
options[:credentials] = credentials if credentials
|
214
234
|
end
|
215
235
|
end
|
216
236
|
|
data/lib/cequel/metal/row.rb
CHANGED
data/lib/cequel/record.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
require 'active_model'
|
3
|
+
require 'weakref'
|
3
4
|
|
4
5
|
require 'cequel'
|
5
6
|
require 'cequel/record/errors'
|
@@ -117,6 +118,17 @@ module Cequel
|
|
117
118
|
def establish_connection(configuration)
|
118
119
|
self.connection = Cequel.connect(configuration)
|
119
120
|
end
|
121
|
+
|
122
|
+
# @return [Array<Class>] All the record classes that are
|
123
|
+
# currently defined.
|
124
|
+
def descendants
|
125
|
+
(@descendants ||= []).select(&:weakref_alive?)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Hook called when new record classes are created.
|
129
|
+
def included(base)
|
130
|
+
@descendants = descendants + [WeakRef.new(base)]
|
131
|
+
end
|
120
132
|
end
|
121
133
|
end
|
122
134
|
end
|
data/lib/cequel/record/errors.rb
CHANGED
@@ -8,6 +8,7 @@ module Cequel
|
|
8
8
|
# @since 1.0.0
|
9
9
|
#
|
10
10
|
MissingAttributeError = Class.new(ArgumentError)
|
11
|
+
|
11
12
|
#
|
12
13
|
# Raised when attempting to read or write an attribute that isn't defined
|
13
14
|
# on the record
|
@@ -15,11 +16,13 @@ module Cequel
|
|
15
16
|
# @since 1.0.0
|
16
17
|
#
|
17
18
|
UnknownAttributeError = Class.new(ArgumentError)
|
19
|
+
|
18
20
|
#
|
19
21
|
# Raised when attempting to load a record by key when that record does not
|
20
22
|
# exist
|
21
23
|
#
|
22
24
|
RecordNotFound = Class.new(StandardError)
|
25
|
+
|
23
26
|
#
|
24
27
|
# Raised when attempting to configure a record in a way that is not
|
25
28
|
# possible
|
@@ -27,10 +30,12 @@ module Cequel
|
|
27
30
|
# @since 1.0.0
|
28
31
|
#
|
29
32
|
InvalidRecordConfiguration = Class.new(StandardError)
|
33
|
+
|
30
34
|
#
|
31
35
|
# Raised when attempting to save a record that is invalid
|
32
36
|
#
|
33
37
|
RecordInvalid = Class.new(StandardError)
|
38
|
+
|
34
39
|
#
|
35
40
|
# Raised when attempting to construct a {RecordSet} that cannot construct
|
36
41
|
# a valid CQL query
|
@@ -38,6 +43,7 @@ module Cequel
|
|
38
43
|
# @since 1.0.0
|
39
44
|
#
|
40
45
|
IllegalQuery = Class.new(StandardError)
|
46
|
+
|
41
47
|
#
|
42
48
|
# Raised when attempting to persist a Cequel::Record without defining all
|
43
49
|
# primary key columns
|
@@ -45,5 +51,11 @@ module Cequel
|
|
45
51
|
# @since 1.0.0
|
46
52
|
#
|
47
53
|
MissingKeyError = Class.new(StandardError)
|
54
|
+
|
55
|
+
#
|
56
|
+
# Raised when attempting to reflect on the schema of a
|
57
|
+
# Cequel::Record without a table name.
|
58
|
+
#
|
59
|
+
MissingTableNameError = Class.new(StandardError)
|
48
60
|
end
|
49
61
|
end
|
@@ -172,12 +172,18 @@ module Cequel
|
|
172
172
|
# @param options [Options] options for save
|
173
173
|
# @option options [Boolean] :validate (true) whether to run validations
|
174
174
|
# before saving
|
175
|
+
# @option options [Symbol] :consistency (:quorum) what consistency with
|
176
|
+
# which to persist the changes
|
177
|
+
# @option options [Integer] :ttl time-to-live of the updated rows in
|
178
|
+
# seconds
|
179
|
+
# @option options [Time] :timestamp the writetime to use for the column
|
180
|
+
# updates
|
175
181
|
# @return [Boolean] true if record saved successfully, false if invalid
|
176
182
|
#
|
177
183
|
# @see Validations#save!
|
178
184
|
#
|
179
185
|
def save(options = {})
|
180
|
-
options.assert_valid_keys(:consistency)
|
186
|
+
options.assert_valid_keys(:consistency, :ttl, :timestamp)
|
181
187
|
if new_record? then create(options)
|
182
188
|
else update(options)
|
183
189
|
end
|
@@ -203,10 +209,15 @@ module Cequel
|
|
203
209
|
#
|
204
210
|
# Remove this record from the database
|
205
211
|
#
|
212
|
+
# @param options [Options] options for deletion
|
213
|
+
# @option options [Symbol] :consistency (:quorum) what consistency with
|
214
|
+
# which to persist the deletion
|
215
|
+
# @option options [Time] :timestamp the writetime to use for the deletion
|
216
|
+
#
|
206
217
|
# @return [Record] self
|
207
218
|
#
|
208
219
|
def destroy(options = {})
|
209
|
-
options.assert_valid_keys(:consistency)
|
220
|
+
options.assert_valid_keys(:consistency, :timestamp)
|
210
221
|
assert_keys_present!
|
211
222
|
metal_scope.delete(options)
|
212
223
|
transient!
|
@@ -271,7 +282,7 @@ module Cequel
|
|
271
282
|
assert_keys_present!
|
272
283
|
connection.batch do
|
273
284
|
updater.execute(options)
|
274
|
-
deleter.execute(options)
|
285
|
+
deleter.execute(options.except(:ttl))
|
275
286
|
@updater, @deleter = nil
|
276
287
|
end
|
277
288
|
end
|
data/lib/cequel/record/schema.rb
CHANGED
@@ -9,6 +9,8 @@ module Cequel
|
|
9
9
|
# {Cequel::Metal::Keyspace} in a future version of Cequel
|
10
10
|
#
|
11
11
|
class Keyspace
|
12
|
+
extend Forwardable
|
13
|
+
|
12
14
|
#
|
13
15
|
# @param keyspace [Keyspace] the keyspace whose schema this object
|
14
16
|
# manipulates
|
@@ -64,6 +66,9 @@ module Cequel
|
|
64
66
|
keyspace.execute("DROP KEYSPACE #{keyspace.name}")
|
65
67
|
end
|
66
68
|
|
69
|
+
# @return [Boolean] true if the keyspace exists
|
70
|
+
def_delegator :keyspace, :exists?
|
71
|
+
|
67
72
|
#
|
68
73
|
# @param name [Symbol] name of the table to read
|
69
74
|
# @return [Table] object representation of the table schema as it
|
@@ -90,7 +90,8 @@ module Cequel
|
|
90
90
|
"Existing clustering columns " \
|
91
91
|
"#{existing.clustering_column_names.join(',')} " \
|
92
92
|
"differ from specified clustering keys " \
|
93
|
-
"#{updated.clustering_column_names.join(',')}"
|
93
|
+
"#{updated.clustering_column_names.join(',')} " \
|
94
|
+
"for #{existing.name}"
|
94
95
|
end
|
95
96
|
end
|
96
97
|
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Cequel
|
2
|
+
module SpecSupport
|
3
|
+
# Provide database preparation behavior that is useful for
|
4
|
+
# spec/test suites.
|
5
|
+
#
|
6
|
+
# For Rails apps adding the following code to the bottom of one's
|
7
|
+
# `spec_helper.rb` (below the `RSpec.configure` block) ensures a
|
8
|
+
# clean and fully synced test db before each test run.
|
9
|
+
#
|
10
|
+
# # one time database setup
|
11
|
+
# Cequel::SpecSupport::Preparation.setup_database
|
12
|
+
#
|
13
|
+
# For non-rails apps adding the following code to the bottom of
|
14
|
+
# one's `spec_helper.rb` (below the `RSpec.configure` block)
|
15
|
+
# ensures a clean and fully synced test db before each test run.
|
16
|
+
#
|
17
|
+
# # one time database setup
|
18
|
+
# Cequel::SpecSupport::Preparation
|
19
|
+
# .setup_database(App.root + "lib/models",
|
20
|
+
# App.root + "lib/other-models")
|
21
|
+
class Preparation
|
22
|
+
#
|
23
|
+
# Provision and sync the database for a spec run.
|
24
|
+
#
|
25
|
+
# @param [Array<String,Pathname>] model_dirs directories in
|
26
|
+
# which Cequel record classes reside. All files in these
|
27
|
+
# directories will be loaded before syncing the
|
28
|
+
# schema. Default: `Rails.root + "app/model"` if `Rails` is
|
29
|
+
# defined; otherwise no models will be autoloaded.
|
30
|
+
# @return [void]
|
31
|
+
#
|
32
|
+
def self.setup_database(*model_dirs)
|
33
|
+
options = model_dirs.extract_options!
|
34
|
+
|
35
|
+
model_dirs =
|
36
|
+
if model_dirs.any? then model_dirs.flatten
|
37
|
+
elsif defined? Rails then [Rails.root + "app/models"]
|
38
|
+
else []
|
39
|
+
end
|
40
|
+
|
41
|
+
preparation = new(model_dirs, options)
|
42
|
+
|
43
|
+
preparation.drop_keyspace
|
44
|
+
preparation.create_keyspace
|
45
|
+
preparation.sync_schema
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(model_dirs = [], options = {})
|
49
|
+
@model_dirs, @options = model_dirs, options
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Ensure the current keyspace does not exist.
|
54
|
+
#
|
55
|
+
# @return [Preparation] self
|
56
|
+
#
|
57
|
+
def drop_keyspace
|
58
|
+
keyspace = Cequel::Record.connection.schema
|
59
|
+
|
60
|
+
keyspace.drop! if keyspace.exists?
|
61
|
+
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Ensure that the necessary keyspace exists.
|
67
|
+
#
|
68
|
+
# @return [Preparation] self
|
69
|
+
#
|
70
|
+
def create_keyspace
|
71
|
+
keyspace = Cequel::Record.connection.schema
|
72
|
+
|
73
|
+
keyspace.create! unless keyspace.exists?
|
74
|
+
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Ensure that the necessary column families exist and match the
|
80
|
+
# models.
|
81
|
+
#
|
82
|
+
# @return [Preparation] self
|
83
|
+
#
|
84
|
+
def sync_schema
|
85
|
+
record_classes.each do |record_class|
|
86
|
+
begin
|
87
|
+
record_class.synchronize_schema
|
88
|
+
unless options[:quiet]
|
89
|
+
puts "Synchronized schema for #{record_class.name}"
|
90
|
+
end
|
91
|
+
|
92
|
+
rescue Record::MissingTableNameError
|
93
|
+
# It is obviously not a real record class if it doesn't have a
|
94
|
+
# table name.
|
95
|
+
unless options[:quiet]
|
96
|
+
STDERR.puts "Skipping anonymous record class without an " \
|
97
|
+
"explicit table name"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
protected
|
106
|
+
|
107
|
+
attr_reader :model_dirs, :options
|
108
|
+
|
109
|
+
#
|
110
|
+
# @return [Array<Class>] all Cequel record classes
|
111
|
+
#
|
112
|
+
def record_classes
|
113
|
+
load_all_models
|
114
|
+
Cequel::Record.descendants
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Loads all files in the models directory under the assumption
|
119
|
+
# that Cequel record classes live there.
|
120
|
+
#
|
121
|
+
def load_all_models
|
122
|
+
model_dirs.each do |directory|
|
123
|
+
Dir.glob(Pathname(directory).join("**", "*.rb")).each do |file_name|
|
124
|
+
require_dependency(file_name)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/lib/cequel/version.rb
CHANGED
@@ -71,4 +71,18 @@ describe Cequel::Metal::Keyspace do
|
|
71
71
|
}.to raise_error(ArgumentError)
|
72
72
|
end
|
73
73
|
end
|
74
|
+
|
75
|
+
describe "#exists?" do
|
76
|
+
it "is true for existent keyspaces" do
|
77
|
+
expect(cequel.exists?).to eq true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "is false for non-existent keyspaces" do
|
81
|
+
nonexistent_keyspace = Cequel.connect host: Cequel::SpecSupport::Helpers.host,
|
82
|
+
port: Cequel::SpecSupport::Helpers.port,
|
83
|
+
keyspace: "totallymadeup"
|
84
|
+
|
85
|
+
expect(nonexistent_keyspace.exists?).to be_false
|
86
|
+
end
|
87
|
+
end
|
74
88
|
end
|
@@ -18,7 +18,7 @@ describe Cequel::Record::Persistence do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
context 'simple keys' do
|
21
|
-
subject { cequel[
|
21
|
+
subject { cequel[Blog.table_name].where(:subdomain => 'cequel').first }
|
22
22
|
|
23
23
|
let!(:blog) do
|
24
24
|
Blog.new do |blog|
|
@@ -57,6 +57,21 @@ describe Cequel::Record::Persistence do
|
|
57
57
|
end.save(consistency: :one)
|
58
58
|
end
|
59
59
|
end
|
60
|
+
|
61
|
+
it 'should save with specified TTL' do
|
62
|
+
Blog.new(subdomain: 'cequel', name: 'Cequel').save(ttl: 10)
|
63
|
+
expect(cequel[Blog.table_name].select_ttl(:name).first.ttl(:name))
|
64
|
+
.to be_within(0.1).of(9.9)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should save with specified timestamp' do
|
68
|
+
timestamp = 1.minute.from_now
|
69
|
+
Blog.new(subdomain: 'cequel-create-ts', name: 'Cequel')
|
70
|
+
.save(timestamp: timestamp)
|
71
|
+
expect(cequel[Blog.table_name].select_timestamp(:name).first.timestamp(:name))
|
72
|
+
.to eq((timestamp.to_f * 1_000_000).to_i)
|
73
|
+
Blog.connection.schema.truncate_table(Blog.table_name)
|
74
|
+
end
|
60
75
|
end
|
61
76
|
|
62
77
|
context 'on update' do
|
@@ -94,6 +109,22 @@ describe Cequel::Record::Persistence do
|
|
94
109
|
blog.save(consistency: :one)
|
95
110
|
end
|
96
111
|
end
|
112
|
+
|
113
|
+
it 'should save with specified TTL' do
|
114
|
+
blog.name = 'Cequel 1.4'
|
115
|
+
blog.save(ttl: 10)
|
116
|
+
expect(cequel[Blog.table_name].select_ttl(:name).first.ttl(:name)).
|
117
|
+
to be_within(0.1).of(9.9)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should save with specified timestamp' do
|
121
|
+
timestamp = 1.minute.from_now
|
122
|
+
blog.name = 'Cequel 1.4'
|
123
|
+
blog.save(timestamp: timestamp)
|
124
|
+
expect(cequel[Blog.table_name].select_timestamp(:name).first.timestamp(:name))
|
125
|
+
.to eq((timestamp.to_f * 1_000_000).to_i)
|
126
|
+
Blog.connection.schema.truncate_table(Blog.table_name)
|
127
|
+
end
|
97
128
|
end
|
98
129
|
end
|
99
130
|
|
@@ -184,12 +215,18 @@ describe Cequel::Record::Persistence do
|
|
184
215
|
blog.destroy(consistency: :one)
|
185
216
|
end
|
186
217
|
end
|
218
|
+
|
219
|
+
it 'should destroy with specified timestamp' do
|
220
|
+
blog = Blog.create(subdomain: 'big-data', name: 'Big Data')
|
221
|
+
blog.destroy(timestamp: 1.minute.ago)
|
222
|
+
expect(cequel[Blog.table_name].where(subdomain: 'big-data').first).to be
|
223
|
+
end
|
187
224
|
end
|
188
225
|
end
|
189
226
|
|
190
227
|
context 'compound keys' do
|
191
228
|
subject do
|
192
|
-
cequel[
|
229
|
+
cequel[Post.table_name].
|
193
230
|
where(:blog_subdomain => 'cassandra', :permalink => 'cequel').first
|
194
231
|
end
|
195
232
|
|
@@ -3,13 +3,16 @@ require File.expand_path('../spec_helper', __FILE__)
|
|
3
3
|
|
4
4
|
describe Cequel::Record::Schema do
|
5
5
|
context 'CQL3 table' do
|
6
|
-
after { cequel.schema.drop_table(
|
7
|
-
subject { cequel.schema.read_table(
|
6
|
+
after { cequel.schema.drop_table(table_name) }
|
7
|
+
subject { cequel.schema.read_table(table_name) }
|
8
|
+
|
9
|
+
let(:table_name) { 'posts_' + SecureRandom.hex(4) }
|
8
10
|
|
9
11
|
let(:model) do
|
12
|
+
model_table_name = table_name
|
10
13
|
Class.new do
|
11
14
|
include Cequel::Record
|
12
|
-
self.table_name =
|
15
|
+
self.table_name = model_table_name
|
13
16
|
|
14
17
|
key :permalink, :text
|
15
18
|
column :title, :text
|
@@ -47,11 +50,13 @@ describe Cequel::Record::Schema do
|
|
47
50
|
end
|
48
51
|
|
49
52
|
context 'CQL3 table with reversed clustering column' do
|
53
|
+
let(:table_name) { 'posts_' + SecureRandom.hex(4) }
|
50
54
|
|
51
55
|
let(:model) do
|
56
|
+
model_table_name = table_name
|
52
57
|
Class.new do
|
53
58
|
include Cequel::Record
|
54
|
-
self.table_name =
|
59
|
+
self.table_name = model_table_name
|
55
60
|
|
56
61
|
key :blog_id, :uuid
|
57
62
|
key :id, :timeuuid, order: :desc
|
@@ -60,8 +65,8 @@ describe Cequel::Record::Schema do
|
|
60
65
|
end
|
61
66
|
|
62
67
|
before { model.synchronize_schema }
|
63
|
-
after { cequel.schema.drop_table(
|
64
|
-
subject { cequel.schema.read_table(
|
68
|
+
after { cequel.schema.drop_table(table_name) }
|
69
|
+
subject { cequel.schema.read_table(table_name) }
|
65
70
|
|
66
71
|
it 'should order clustering column descending' do
|
67
72
|
subject.clustering_columns.first.clustering_order.should == :desc
|
@@ -69,10 +74,13 @@ describe Cequel::Record::Schema do
|
|
69
74
|
end
|
70
75
|
|
71
76
|
context 'wide-row legacy table' do
|
77
|
+
let(:table_name) { 'legacy_posts_' + SecureRandom.hex(4) }
|
78
|
+
|
72
79
|
let(:legacy_model) do
|
80
|
+
model_table_name = table_name
|
73
81
|
Class.new do
|
74
82
|
include Cequel::Record
|
75
|
-
self.table_name =
|
83
|
+
self.table_name = model_table_name
|
76
84
|
|
77
85
|
key :blog_subdomain, :text
|
78
86
|
key :id, :uuid
|
@@ -81,8 +89,8 @@ describe Cequel::Record::Schema do
|
|
81
89
|
compact_storage
|
82
90
|
end
|
83
91
|
end
|
84
|
-
after { cequel.schema.drop_table(
|
85
|
-
subject { cequel.schema.read_table(
|
92
|
+
after { cequel.schema.drop_table(table_name) }
|
93
|
+
subject { cequel.schema.read_table(table_name) }
|
86
94
|
|
87
95
|
context 'new model' do
|
88
96
|
before { legacy_model.synchronize_schema }
|
@@ -96,7 +104,7 @@ describe Cequel::Record::Schema do
|
|
96
104
|
context 'existing model', thrift: true do
|
97
105
|
before do
|
98
106
|
legacy_connection.execute(<<-CQL2)
|
99
|
-
CREATE COLUMNFAMILY
|
107
|
+
CREATE COLUMNFAMILY #{table_name} (blog_subdomain text PRIMARY KEY)
|
100
108
|
WITH comparator=uuid AND default_validation=text
|
101
109
|
CQL2
|
102
110
|
legacy_model.synchronize_schema
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
require "cequel/spec_support"
|
4
|
+
|
5
|
+
describe Cequel::SpecSupport::Preparation do
|
6
|
+
subject(:prep) { described_class.new([], quiet: true) }
|
7
|
+
let(:keyspace) { cequel }
|
8
|
+
|
9
|
+
it "returns itself from #drop_keyspace" do
|
10
|
+
expect(prep.drop_keyspace).to eq prep
|
11
|
+
end
|
12
|
+
|
13
|
+
it "returns itself from #create_keyspace" do
|
14
|
+
expect(prep.create_keyspace).to eq prep
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns itself from #sync_schema" do
|
18
|
+
expect(prep.sync_schema).to eq prep
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
context "existing keyspace" do
|
23
|
+
it "can be deleted" do
|
24
|
+
prep.drop_keyspace
|
25
|
+
expect(keyspace.exists?).to eq false
|
26
|
+
end
|
27
|
+
|
28
|
+
it "doesn't cause failure upon creation request" do
|
29
|
+
expect{ prep.create_keyspace }.not_to raise_error
|
30
|
+
expect(keyspace.exists?).to eq true
|
31
|
+
end
|
32
|
+
|
33
|
+
it "allows tables to be synced" do
|
34
|
+
3.times do GC.start end # get rid of most of the crufty classes
|
35
|
+
|
36
|
+
table_name = "model_in_nonstandard_place_" + SecureRandom.hex(4)
|
37
|
+
rec_class = Class.new do
|
38
|
+
include Cequel::Record
|
39
|
+
self.table_name = table_name
|
40
|
+
key :sk, :uuid
|
41
|
+
end
|
42
|
+
|
43
|
+
prep.sync_schema
|
44
|
+
expect(keyspace).to contain_table table_name
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "keyspace doesn't exist" do
|
49
|
+
before do
|
50
|
+
Cequel::Record.connection.schema.drop!
|
51
|
+
end
|
52
|
+
|
53
|
+
it "doesn't cause failure upon drop requests" do
|
54
|
+
expect{ prep.drop_keyspace }.not_to raise_error
|
55
|
+
end
|
56
|
+
|
57
|
+
it "allows keyspace can be created" do
|
58
|
+
prep.create_keyspace
|
59
|
+
expect(keyspace).to exist
|
60
|
+
end
|
61
|
+
|
62
|
+
it "causes #sync_schema to fail" do
|
63
|
+
expect{ prep.sync_schema }.to raise_error
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# background
|
68
|
+
|
69
|
+
after { Cequel::Record.connection.schema.create! rescue nil }
|
70
|
+
|
71
|
+
matcher :contain_table do |table_name|
|
72
|
+
match do |keyspace|
|
73
|
+
keyspace.execute(<<-CQL).any?
|
74
|
+
SELECT columnfamily_name
|
75
|
+
FROM System.schema_columnfamilies
|
76
|
+
WHERE keyspace_name='#{keyspace.name}'
|
77
|
+
AND columnfamily_name='#{table_name}'
|
78
|
+
CQL
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/spec/support/helpers.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
module Cequel
|
3
|
-
|
4
3
|
module SpecSupport
|
5
4
|
module Macros
|
6
5
|
def model(class_name, options = {}, &block)
|
@@ -16,7 +15,7 @@ module Cequel
|
|
16
15
|
metadata[:models].each do |name, (options, block)|
|
17
16
|
clazz = Class.new do
|
18
17
|
include Cequel::Record
|
19
|
-
self.table_name = name.to_s.tableize
|
18
|
+
self.table_name = name.to_s.tableize + "_" + SecureRandom.hex(4)
|
20
19
|
class_eval(&block)
|
21
20
|
end
|
22
21
|
Object.module_eval { const_set(name, clazz) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Brown
|
@@ -20,7 +20,7 @@ authors:
|
|
20
20
|
autorequire:
|
21
21
|
bindir: bin
|
22
22
|
cert_chain: []
|
23
|
-
date: 2014-06-
|
23
|
+
date: 2014-06-09 00:00:00.000000000 Z
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activemodel
|
@@ -224,6 +224,8 @@ files:
|
|
224
224
|
- lib/cequel/schema/table_updater.rb
|
225
225
|
- lib/cequel/schema/table_writer.rb
|
226
226
|
- lib/cequel/schema/update_table_dsl.rb
|
227
|
+
- lib/cequel/spec_support.rb
|
228
|
+
- lib/cequel/spec_support/preparation.rb
|
227
229
|
- lib/cequel/type.rb
|
228
230
|
- lib/cequel/util.rb
|
229
231
|
- lib/cequel/uuids.rb
|
@@ -254,6 +256,7 @@ files:
|
|
254
256
|
- spec/examples/schema/table_updater_spec.rb
|
255
257
|
- spec/examples/schema/table_writer_spec.rb
|
256
258
|
- spec/examples/spec_helper.rb
|
259
|
+
- spec/examples/spec_support/preparation_spec.rb
|
257
260
|
- spec/examples/type_spec.rb
|
258
261
|
- spec/examples/uuids_spec.rb
|
259
262
|
- spec/shared/readable_dictionary.rb
|
@@ -312,6 +315,7 @@ test_files:
|
|
312
315
|
- spec/examples/schema/table_updater_spec.rb
|
313
316
|
- spec/examples/schema/table_writer_spec.rb
|
314
317
|
- spec/examples/spec_helper.rb
|
318
|
+
- spec/examples/spec_support/preparation_spec.rb
|
315
319
|
- spec/examples/type_spec.rb
|
316
320
|
- spec/examples/uuids_spec.rb
|
317
321
|
has_rdoc: true
|