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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cequel.rb +1 -1
  3. data/lib/cequel/record.rb +62 -0
  4. data/lib/cequel/{model → record}/association_collection.rb +1 -1
  5. data/lib/cequel/{model → record}/associations.rb +1 -1
  6. data/lib/cequel/{model → record}/belongs_to_association.rb +1 -1
  7. data/lib/cequel/{model → record}/callbacks.rb +1 -1
  8. data/lib/cequel/{model → record}/collection.rb +1 -1
  9. data/lib/cequel/{model → record}/dirty.rb +1 -1
  10. data/lib/cequel/{model → record}/errors.rb +1 -1
  11. data/lib/cequel/{model → record}/has_many_association.rb +1 -1
  12. data/lib/cequel/{model → record}/mass_assignment.rb +1 -1
  13. data/lib/cequel/{model → record}/persistence.rb +11 -11
  14. data/lib/cequel/{model → record}/properties.rb +69 -15
  15. data/lib/cequel/{model → record}/railtie.rb +3 -3
  16. data/lib/cequel/{model → record}/record_set.rb +67 -57
  17. data/lib/cequel/record/schema.rb +76 -0
  18. data/lib/cequel/record/scoped.rb +53 -0
  19. data/lib/cequel/{model → record}/secondary_indexes.rb +1 -1
  20. data/lib/cequel/{model → record}/validations.rb +1 -1
  21. data/lib/cequel/schema/table.rb +18 -9
  22. data/lib/cequel/version.rb +1 -1
  23. data/spec/examples/{model → record}/associations_spec.rb +8 -8
  24. data/spec/examples/{model → record}/callbacks_spec.rb +1 -1
  25. data/spec/examples/{model → record}/dirty_spec.rb +1 -1
  26. data/spec/examples/{model → record}/list_spec.rb +1 -1
  27. data/spec/examples/{model → record}/map_spec.rb +1 -1
  28. data/spec/examples/{model → record}/mass_assignment_spec.rb +1 -1
  29. data/spec/examples/{model → record}/naming_spec.rb +0 -0
  30. data/spec/examples/{model → record}/persistence_spec.rb +1 -1
  31. data/spec/examples/{model → record}/properties_spec.rb +25 -2
  32. data/spec/examples/{model → record}/record_set_spec.rb +28 -7
  33. data/spec/examples/{model → record}/schema_spec.rb +3 -2
  34. data/spec/examples/record/scoped_spec.rb +13 -0
  35. data/spec/examples/{model → record}/secondary_index_spec.rb +1 -1
  36. data/spec/examples/{model → record}/serialization_spec.rb +1 -1
  37. data/spec/examples/{model → record}/set_spec.rb +1 -1
  38. data/spec/examples/{model → record}/spec_helper.rb +0 -0
  39. data/spec/examples/{model → record}/validations_spec.rb +4 -4
  40. data/spec/examples/spec_helper.rb +2 -2
  41. data/spec/support/helpers.rb +2 -1
  42. metadata +54 -64
  43. data/lib/cequel/model.rb +0 -30
  44. data/lib/cequel/model/base.rb +0 -84
  45. data/lib/cequel/model/schema.rb +0 -34
  46. data/lib/cequel/model/scoped.rb +0 -19
  47. data/spec/models/asset.rb +0 -21
  48. data/spec/models/asset_observer.rb +0 -5
  49. data/spec/models/blog.rb +0 -14
  50. data/spec/models/blog_posts.rb +0 -6
  51. data/spec/models/category.rb +0 -9
  52. data/spec/models/comment.rb +0 -12
  53. data/spec/models/comment_counts.rb +0 -8
  54. data/spec/models/photo.rb +0 -5
  55. data/spec/models/post.rb +0 -88
  56. data/spec/models/post_comments.rb +0 -14
  57. 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
@@ -1,6 +1,6 @@
1
1
  module Cequel
2
2
 
3
- module Model
3
+ module Record
4
4
 
5
5
  module SecondaryIndexes
6
6
 
@@ -1,6 +1,6 @@
1
1
  module Cequel
2
2
 
3
- module Model
3
+ module Record
4
4
 
5
5
  module Validations
6
6
 
@@ -34,13 +34,15 @@ module Cequel
34
34
  end
35
35
 
36
36
  def add_partition_key(name, type)
37
- column = PartitionKey.new(name, type(type))
38
- @partition_key_columns << add_column(column)
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
- column = ClusteringColumn.new(name, type(type), clustering_order)
43
- @clustering_columns << add_column(column)
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
- @data_columns << add_column(List.new(name, type(type)))
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
- @data_columns << add_column(Set.new(name, type(type)))
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
- @data_columns <<
62
- add_column(Map.new(name, type(key_type), type(value_type)))
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
- @properties[name] = TableProperty.new(name, value)
73
+ TableProperty.new(name, value).tap do |property|
74
+ @properties[name] = property
75
+ end
67
76
  end
68
77
 
69
78
  def column(name)
@@ -1,3 +1,3 @@
1
1
  module Cequel
2
- VERSION = '1.0.0.pre.2'
2
+ VERSION = '1.0.0.pre.3'
3
3
  end
@@ -1,6 +1,6 @@
1
1
  require_relative 'spec_helper'
2
2
 
3
- describe Cequel::Model::Associations do
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(Cequel::Model::Base) do
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::Model::InvalidRecordConfiguration)
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(Cequel::Model::Base) do
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::Model::InvalidRecordConfiguration)
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
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
- describe Cequel::Model::Callbacks do
3
+ describe Cequel::Record::Callbacks do
4
4
  model :Post do
5
5
  key :permalink, :text
6
6
  column :title, :text
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
- describe Cequel::Model::Dirty do
3
+ describe Cequel::Record::Dirty do
4
4
  model :Post do
5
5
  key :permalink, :text
6
6
  column :title, :text
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
- describe Cequel::Model::List do
3
+ describe Cequel::Record::List do
4
4
  model :Post do
5
5
  key :permalink, :text
6
6
  column :title, :text
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
- describe Cequel::Model::Map do
3
+ describe Cequel::Record::Map do
4
4
  model :Post do
5
5
  key :permalink, :text
6
6
  column :title, :text
@@ -1,6 +1,6 @@
1
1
  require_relative 'spec_helper'
2
2
 
3
- describe Cequel::Model::MassAssignment do
3
+ describe Cequel::Record::MassAssignment do
4
4
  context 'with strong parameters', :rails => '~> 4.0' do
5
5
  model :Post do
6
6
  key :permalink, :text
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
- describe Cequel::Model::Persistence do
3
+ describe Cequel::Record::Persistence do
4
4
  model :Blog do
5
5
  key :subdomain, :text
6
6
  column :name, :text
@@ -1,7 +1,6 @@
1
- require 'cequel/model'
2
1
  require File.expand_path('../spec_helper', __FILE__)
3
2
 
4
- describe Cequel::Model::Properties do
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::Model::RecordSet do
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::Model::RecordNotFound)
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::Model::RecordNotFound)
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') }.to raise_error(NoMethodError)
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(NoMethodError)
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::Model::MissingAttributeError) }
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::Model::IllegalQuery)
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