cequel 1.0.0.pre.2 → 1.0.0.pre.3
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.
- checksums.yaml +4 -4
- data/lib/cequel.rb +1 -1
- data/lib/cequel/record.rb +62 -0
- data/lib/cequel/{model → record}/association_collection.rb +1 -1
- data/lib/cequel/{model → record}/associations.rb +1 -1
- data/lib/cequel/{model → record}/belongs_to_association.rb +1 -1
- data/lib/cequel/{model → record}/callbacks.rb +1 -1
- data/lib/cequel/{model → record}/collection.rb +1 -1
- data/lib/cequel/{model → record}/dirty.rb +1 -1
- data/lib/cequel/{model → record}/errors.rb +1 -1
- data/lib/cequel/{model → record}/has_many_association.rb +1 -1
- data/lib/cequel/{model → record}/mass_assignment.rb +1 -1
- data/lib/cequel/{model → record}/persistence.rb +11 -11
- data/lib/cequel/{model → record}/properties.rb +69 -15
- data/lib/cequel/{model → record}/railtie.rb +3 -3
- data/lib/cequel/{model → record}/record_set.rb +67 -57
- data/lib/cequel/record/schema.rb +76 -0
- data/lib/cequel/record/scoped.rb +53 -0
- data/lib/cequel/{model → record}/secondary_indexes.rb +1 -1
- data/lib/cequel/{model → record}/validations.rb +1 -1
- data/lib/cequel/schema/table.rb +18 -9
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/{model → record}/associations_spec.rb +8 -8
- data/spec/examples/{model → record}/callbacks_spec.rb +1 -1
- data/spec/examples/{model → record}/dirty_spec.rb +1 -1
- data/spec/examples/{model → record}/list_spec.rb +1 -1
- data/spec/examples/{model → record}/map_spec.rb +1 -1
- data/spec/examples/{model → record}/mass_assignment_spec.rb +1 -1
- data/spec/examples/{model → record}/naming_spec.rb +0 -0
- data/spec/examples/{model → record}/persistence_spec.rb +1 -1
- data/spec/examples/{model → record}/properties_spec.rb +25 -2
- data/spec/examples/{model → record}/record_set_spec.rb +28 -7
- data/spec/examples/{model → record}/schema_spec.rb +3 -2
- data/spec/examples/record/scoped_spec.rb +13 -0
- data/spec/examples/{model → record}/secondary_index_spec.rb +1 -1
- data/spec/examples/{model → record}/serialization_spec.rb +1 -1
- data/spec/examples/{model → record}/set_spec.rb +1 -1
- data/spec/examples/{model → record}/spec_helper.rb +0 -0
- data/spec/examples/{model → record}/validations_spec.rb +4 -4
- data/spec/examples/spec_helper.rb +2 -2
- data/spec/support/helpers.rb +2 -1
- metadata +54 -64
- data/lib/cequel/model.rb +0 -30
- data/lib/cequel/model/base.rb +0 -84
- data/lib/cequel/model/schema.rb +0 -34
- data/lib/cequel/model/scoped.rb +0 -19
- data/spec/models/asset.rb +0 -21
- data/spec/models/asset_observer.rb +0 -5
- data/spec/models/blog.rb +0 -14
- data/spec/models/blog_posts.rb +0 -6
- data/spec/models/category.rb +0 -9
- data/spec/models/comment.rb +0 -12
- data/spec/models/comment_counts.rb +0 -8
- data/spec/models/photo.rb +0 -5
- data/spec/models/post.rb +0 -88
- data/spec/models/post_comments.rb +0 -14
- data/spec/models/post_observer.rb +0 -43
@@ -0,0 +1,76 @@
|
|
1
|
+
module Cequel
|
2
|
+
|
3
|
+
module Record
|
4
|
+
|
5
|
+
module Schema
|
6
|
+
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
included do
|
11
|
+
class_attribute :table_name, :instance_writer => false
|
12
|
+
self.table_name = name.tableize.to_sym unless name.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
extend Forwardable
|
17
|
+
|
18
|
+
def_delegators :table_schema, :key_columns, :key_column_names,
|
19
|
+
:partition_key_columns, :clustering_columns
|
20
|
+
def_delegator :table_schema, :column, :reflect_on_column
|
21
|
+
|
22
|
+
def synchronize_schema
|
23
|
+
Cequel::Schema::TableSynchronizer.
|
24
|
+
apply(connection, read_schema, table_schema)
|
25
|
+
end
|
26
|
+
|
27
|
+
def read_schema
|
28
|
+
connection.schema.read_table(table_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def table_schema
|
32
|
+
@table_schema ||= Cequel::Schema::Table.new(table_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def key(name, type, options = {})
|
38
|
+
super
|
39
|
+
table_schema.add_key(name, type)
|
40
|
+
end
|
41
|
+
|
42
|
+
def column(name, type, options = {})
|
43
|
+
super
|
44
|
+
table_schema.add_data_column(name, type, options[:index])
|
45
|
+
end
|
46
|
+
|
47
|
+
def list(name, type, options = {})
|
48
|
+
super
|
49
|
+
table_schema.add_list(name, type)
|
50
|
+
end
|
51
|
+
|
52
|
+
def set(name, type, options = {})
|
53
|
+
super
|
54
|
+
table_schema.add_set(name, type)
|
55
|
+
end
|
56
|
+
|
57
|
+
def map(name, key_type, value_type, options = {})
|
58
|
+
super
|
59
|
+
table_schema.add_map(name, key_type, value_type)
|
60
|
+
end
|
61
|
+
|
62
|
+
def table_property(name, value)
|
63
|
+
table_schema.add_property(name, value)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
def_delegator 'self.class', :table_schema
|
70
|
+
protected :table_schema
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Cequel
|
2
|
+
|
3
|
+
module Record
|
4
|
+
|
5
|
+
module Scoped
|
6
|
+
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
def_delegators :current_scope,
|
14
|
+
*(RecordSet.public_instance_methods(false) - Object.instance_methods)
|
15
|
+
|
16
|
+
def current_scope
|
17
|
+
delegating_scope || RecordSet.new(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def with_scope(record_set)
|
21
|
+
previous_scope = delegating_scope
|
22
|
+
self.delegating_scope = record_set
|
23
|
+
yield
|
24
|
+
ensure
|
25
|
+
self.delegating_scope = previous_scope
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def delegating_scope
|
31
|
+
Thread.current[delegating_scope_key]
|
32
|
+
end
|
33
|
+
|
34
|
+
def delegating_scope=(delegating_scope)
|
35
|
+
Thread.current[delegating_scope_key] = delegating_scope
|
36
|
+
end
|
37
|
+
|
38
|
+
def delegating_scope_key
|
39
|
+
@delegating_scope_key ||= :"#{name}::delegating_scope"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize_new_record(*)
|
45
|
+
super
|
46
|
+
@attributes.merge!(self.class.current_scope.scoped_key_attributes)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/lib/cequel/schema/table.rb
CHANGED
@@ -34,13 +34,15 @@ module Cequel
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def add_partition_key(name, type)
|
37
|
-
|
38
|
-
|
37
|
+
PartitionKey.new(name, type(type)).tap do |column|
|
38
|
+
@partition_key_columns << add_column(column)
|
39
|
+
end
|
39
40
|
end
|
40
41
|
|
41
42
|
def add_clustering_column(name, type, clustering_order = nil)
|
42
|
-
|
43
|
-
|
43
|
+
ClusteringColumn.new(name, type(type), clustering_order).tap do |column|
|
44
|
+
@clustering_columns << add_column(column)
|
45
|
+
end
|
44
46
|
end
|
45
47
|
|
46
48
|
def add_data_column(name, type, index_name)
|
@@ -50,20 +52,27 @@ module Cequel
|
|
50
52
|
end
|
51
53
|
|
52
54
|
def add_list(name, type)
|
53
|
-
|
55
|
+
List.new(name, type(type)).tap do |column|
|
56
|
+
@data_columns << add_column(column)
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
def add_set(name, type)
|
57
|
-
|
61
|
+
Set.new(name, type(type)).tap do |column|
|
62
|
+
@data_columns << add_column(column)
|
63
|
+
end
|
58
64
|
end
|
59
65
|
|
60
66
|
def add_map(name, key_type, value_type)
|
61
|
-
|
62
|
-
|
67
|
+
Map.new(name, type(key_type), type(value_type)).tap do |column|
|
68
|
+
@data_columns << add_column(column)
|
69
|
+
end
|
63
70
|
end
|
64
71
|
|
65
72
|
def add_property(name, value)
|
66
|
-
|
73
|
+
TableProperty.new(name, value).tap do |property|
|
74
|
+
@properties[name] = property
|
75
|
+
end
|
67
76
|
end
|
68
77
|
|
69
78
|
def column(name)
|
data/lib/cequel/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative 'spec_helper'
|
2
2
|
|
3
|
-
describe Cequel::
|
3
|
+
describe Cequel::Record::Associations do
|
4
4
|
|
5
5
|
model :Blog do
|
6
6
|
key :subdomain, :text
|
@@ -16,7 +16,7 @@ describe Cequel::Model::Associations do
|
|
16
16
|
|
17
17
|
model :Post do
|
18
18
|
belongs_to :blog
|
19
|
-
key :id, :uuid
|
19
|
+
key :id, :uuid, auto: true
|
20
20
|
column :title, :text
|
21
21
|
end
|
22
22
|
|
@@ -60,20 +60,22 @@ describe Cequel::Model::Associations do
|
|
60
60
|
|
61
61
|
it 'should not allow declaring belongs_to after key' do
|
62
62
|
expect do
|
63
|
-
Class.new
|
63
|
+
Class.new do
|
64
|
+
include Cequel::Record
|
64
65
|
key :permalink, :text
|
65
66
|
belongs_to :blog
|
66
67
|
end
|
67
|
-
end.to raise_error(Cequel::
|
68
|
+
end.to raise_error(Cequel::Record::InvalidRecordConfiguration)
|
68
69
|
end
|
69
70
|
|
70
71
|
it 'should not allow declaring belongs_to more than once' do
|
71
72
|
expect do
|
72
|
-
Class.new
|
73
|
+
Class.new do
|
74
|
+
include Cequel::Record
|
73
75
|
belongs_to :blog
|
74
76
|
belongs_to :user
|
75
77
|
end
|
76
|
-
end.to raise_error(Cequel::
|
78
|
+
end.to raise_error(Cequel::Record::InvalidRecordConfiguration)
|
77
79
|
end
|
78
80
|
|
79
81
|
end
|
@@ -84,7 +86,6 @@ describe Cequel::Model::Associations do
|
|
84
86
|
3.times.map do |i|
|
85
87
|
Post.new do |post|
|
86
88
|
post.blog = blog
|
87
|
-
post.id = CassandraCQL::UUID.new
|
88
89
|
post.title = "Post #{i}"
|
89
90
|
end.tap(&:save)
|
90
91
|
end
|
@@ -93,7 +94,6 @@ describe Cequel::Model::Associations do
|
|
93
94
|
3.times.map do |i|
|
94
95
|
Post.new do |post|
|
95
96
|
post.blog_subdomain = 'mycat'
|
96
|
-
post.id = CassandraCQL::UUID.new
|
97
97
|
post.title = "My Cat #{i}"
|
98
98
|
end.tap(&:save)
|
99
99
|
end
|
File without changes
|
@@ -1,7 +1,6 @@
|
|
1
|
-
require 'cequel/model'
|
2
1
|
require File.expand_path('../spec_helper', __FILE__)
|
3
2
|
|
4
|
-
describe Cequel::
|
3
|
+
describe Cequel::Record::Properties do
|
5
4
|
|
6
5
|
describe 'property accessors' do
|
7
6
|
model :Post do
|
@@ -125,4 +124,28 @@ describe Cequel::Model::Properties do
|
|
125
124
|
Post.new.shares.should == {'facebook' => 0}
|
126
125
|
end
|
127
126
|
end
|
127
|
+
|
128
|
+
describe 'dynamic property generation' do
|
129
|
+
model :Post do
|
130
|
+
key :id, :uuid, auto: true
|
131
|
+
column :title, :text, default: -> { "Post #{Date.today}" }
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should auto-generate UUID key' do
|
135
|
+
Post.new.id.should be_a(CassandraCQL::UUID)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should raise ArgumentError if auto specified for non-UUID' do
|
139
|
+
expect do
|
140
|
+
Class.new do
|
141
|
+
include Cequel::Record
|
142
|
+
key :subdomain, :text, auto: true
|
143
|
+
end
|
144
|
+
end.to raise_error(ArgumentError)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should run default proc' do
|
148
|
+
Post.new.title.should == "Post #{Date.today}"
|
149
|
+
end
|
150
|
+
end
|
128
151
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path('../spec_helper', __FILE__)
|
2
2
|
|
3
|
-
describe Cequel::
|
3
|
+
describe Cequel::Record::RecordSet do
|
4
4
|
model :Blog do
|
5
5
|
key :subdomain, :text
|
6
6
|
column :name, :text
|
@@ -17,6 +17,10 @@ describe Cequel::Model::RecordSet do
|
|
17
17
|
list :tags, :text
|
18
18
|
set :categories, :text
|
19
19
|
map :shares, :text, :int
|
20
|
+
|
21
|
+
def self.latest(count)
|
22
|
+
reverse.limit(count)
|
23
|
+
end
|
20
24
|
end
|
21
25
|
|
22
26
|
let(:subdomains) { [] }
|
@@ -64,7 +68,7 @@ describe Cequel::Model::RecordSet do
|
|
64
68
|
|
65
69
|
specify do
|
66
70
|
expect { Blog.find('bogus') }.
|
67
|
-
to raise_error(Cequel::
|
71
|
+
to raise_error(Cequel::Record::RecordNotFound)
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
@@ -82,7 +86,7 @@ describe Cequel::Model::RecordSet do
|
|
82
86
|
|
83
87
|
specify do
|
84
88
|
expect { Post['cequel'].find('bogus')}.
|
85
|
-
to raise_error(Cequel::
|
89
|
+
to raise_error(Cequel::Record::RecordNotFound)
|
86
90
|
end
|
87
91
|
end
|
88
92
|
end
|
@@ -181,7 +185,8 @@ describe Cequel::Model::RecordSet do
|
|
181
185
|
end
|
182
186
|
|
183
187
|
it 'should raise ArgumentError when called on partition key' do
|
184
|
-
expect { Post.from('cassandra') }.
|
188
|
+
expect { Post.from('cassandra') }.
|
189
|
+
to raise_error(Cequel::Record::IllegalQuery)
|
185
190
|
end
|
186
191
|
end
|
187
192
|
|
@@ -228,7 +233,7 @@ describe Cequel::Model::RecordSet do
|
|
228
233
|
end
|
229
234
|
|
230
235
|
it 'should raise an error if range key is a partition key' do
|
231
|
-
expect { Post.all.reverse }.to raise_error(
|
236
|
+
expect { Post.all.reverse }.to raise_error(Cequel::Record::IllegalQuery)
|
232
237
|
end
|
233
238
|
end
|
234
239
|
|
@@ -236,6 +241,11 @@ describe Cequel::Model::RecordSet do
|
|
236
241
|
it 'should return the last instance' do
|
237
242
|
Post.at('cassandra').last.title.should == "Cequel 4"
|
238
243
|
end
|
244
|
+
|
245
|
+
it 'should return the last N instances if specified' do
|
246
|
+
Post.at('cassandra').last(3).map(&:title).
|
247
|
+
should == ["Cequel 2", "Cequel 3", "Cequel 4"]
|
248
|
+
end
|
239
249
|
end
|
240
250
|
|
241
251
|
describe '#first' do
|
@@ -268,7 +278,7 @@ describe Cequel::Model::RecordSet do
|
|
268
278
|
it { should_not be_loaded(:description) }
|
269
279
|
specify { expect { subject.name }.to_not raise_error }
|
270
280
|
specify { expect { subject.description }.
|
271
|
-
to raise_error(Cequel::
|
281
|
+
to raise_error(Cequel::Record::MissingAttributeError) }
|
272
282
|
end
|
273
283
|
|
274
284
|
context 'with block' do
|
@@ -303,7 +313,7 @@ describe Cequel::Model::RecordSet do
|
|
303
313
|
it 'should raise IllegalQuery if applied twice' do
|
304
314
|
expect { Post.where(:author_id, uuids.first).
|
305
315
|
where(:author_name, 'Mat Brown') }.
|
306
|
-
to raise_error(Cequel::
|
316
|
+
to raise_error(Cequel::Record::IllegalQuery)
|
307
317
|
end
|
308
318
|
end
|
309
319
|
|
@@ -313,4 +323,15 @@ describe Cequel::Model::RecordSet do
|
|
313
323
|
end
|
314
324
|
end
|
315
325
|
|
326
|
+
describe 'scope methods' do
|
327
|
+
it 'should delegate unknown methods to class singleton with current scope' do
|
328
|
+
Post['cassandra'].latest(3).map(&:permalink).
|
329
|
+
should == %w(cequel4 cequel3 cequel2)
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'should raise NoMethodError if undefined method called' do
|
333
|
+
expect { Post['cassandra'].bogus }.to raise_error(NoMethodError)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
316
337
|
end
|