cequel 1.0.0.pre.3 → 1.0.0.pre.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cequel/record/associations.rb +24 -1
- data/lib/cequel/record/schema.rb +5 -1
- data/lib/cequel/schema/table_reader.rb +24 -14
- data/lib/cequel/schema/table_synchronizer.rb +13 -6
- data/lib/cequel/schema/table_updater.rb +1 -1
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/record/associations_spec.rb +89 -1
- data/spec/examples/record/schema_spec.rb +74 -31
- data/spec/examples/schema/table_reader_spec.rb +69 -8
- data/spec/support/helpers.rb +15 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af518e804a2ce5cf3e021b7a2ba92302011c0cd4
|
4
|
+
data.tar.gz: dadafdee945a8c961ac58fcf29ed3a76f84e616e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f90d210ad3a9ab787fcd6e70bba0e950f5983ade9d41f5f17f160b91eab470a84e4f5ca4f828be938db04ccb4bafda1f1be5fba1ea2db75667a2a82ee0d6043b
|
7
|
+
data.tar.gz: 22436304a692c25bd34ce86b58d317630b81af527a28234e3d4bc4884617699cb0fc1092138e7c1a54867059f8118b183e8c4263bef175f735041948a5a53a93
|
@@ -32,11 +32,23 @@ module Cequel
|
|
32
32
|
def_parent_association_accessors
|
33
33
|
end
|
34
34
|
|
35
|
-
def has_many(name)
|
35
|
+
def has_many(name, options = {})
|
36
|
+
options.assert_valid_keys(:dependent)
|
37
|
+
|
36
38
|
association = HasManyAssociation.new(self, name.to_sym)
|
37
39
|
self.child_associations =
|
38
40
|
child_associations.merge(name => association)
|
39
41
|
def_child_association_reader(association)
|
42
|
+
|
43
|
+
case options[:dependent]
|
44
|
+
when :destroy
|
45
|
+
after_destroy { delete_children(name, true) }
|
46
|
+
when :delete
|
47
|
+
after_destroy { delete_children(name) }
|
48
|
+
when nil
|
49
|
+
else
|
50
|
+
raise ArgumentError, "Invalid option #{options[:dependent].inspect} provided for :dependent. Specify :destroy or :delete."
|
51
|
+
end
|
40
52
|
end
|
41
53
|
|
42
54
|
private
|
@@ -117,6 +129,17 @@ module Cequel
|
|
117
129
|
ivar, AssociationCollection.new(association_record_set))
|
118
130
|
end
|
119
131
|
|
132
|
+
def delete_children(association_name, run_callbacks = false)
|
133
|
+
if run_callbacks
|
134
|
+
self.send(association_name).each do |c|
|
135
|
+
c.run_callbacks(:destroy)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
connection[association_name].where(
|
139
|
+
send(association_name).scoped_key_attributes
|
140
|
+
).delete
|
141
|
+
end
|
142
|
+
|
120
143
|
end
|
121
144
|
|
122
145
|
end
|
data/lib/cequel/record/schema.rb
CHANGED
@@ -16,7 +16,7 @@ module Cequel
|
|
16
16
|
extend Forwardable
|
17
17
|
|
18
18
|
def_delegators :table_schema, :key_columns, :key_column_names,
|
19
|
-
:partition_key_columns, :clustering_columns
|
19
|
+
:partition_key_columns, :clustering_columns, :compact_storage?
|
20
20
|
def_delegator :table_schema, :column, :reflect_on_column
|
21
21
|
|
22
22
|
def synchronize_schema
|
@@ -63,6 +63,10 @@ module Cequel
|
|
63
63
|
table_schema.add_property(name, value)
|
64
64
|
end
|
65
65
|
|
66
|
+
def compact_storage
|
67
|
+
table_schema.compact_storage = true
|
68
|
+
end
|
69
|
+
|
66
70
|
end
|
67
71
|
|
68
72
|
protected
|
@@ -56,6 +56,8 @@ module Cequel
|
|
56
56
|
comparators = parse_composite_types(table_data['comparator'])
|
57
57
|
unless comparators
|
58
58
|
table.compact_storage = true
|
59
|
+
return unless column_data.empty?
|
60
|
+
column_aliases << nil if column_aliases.empty?
|
59
61
|
comparators = [table_data['comparator']]
|
60
62
|
end
|
61
63
|
column_aliases.zip(comparators) do |column_alias, type|
|
@@ -64,7 +66,7 @@ module Cequel
|
|
64
66
|
clustering_order = :desc
|
65
67
|
end
|
66
68
|
table.add_clustering_column(
|
67
|
-
column_alias.to_sym,
|
69
|
+
column_alias.try(:to_sym),
|
68
70
|
Type.lookup_internal(type),
|
69
71
|
clustering_order
|
70
72
|
)
|
@@ -72,19 +74,27 @@ module Cequel
|
|
72
74
|
end
|
73
75
|
|
74
76
|
def read_data_columns
|
75
|
-
column_data.
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
77
|
+
if column_data.empty?
|
78
|
+
table.add_data_column(
|
79
|
+
table_data['value_alias'],
|
80
|
+
Type.lookup_internal(table_data['default_validator']),
|
81
|
+
false
|
82
|
+
)
|
83
|
+
else
|
84
|
+
column_data.each do |result|
|
85
|
+
if COLLECTION_TYPE_PATTERN =~ result['validator']
|
86
|
+
read_collection_column(
|
87
|
+
result['column_name'],
|
88
|
+
$1.underscore,
|
89
|
+
*$2.split(',')
|
90
|
+
)
|
91
|
+
else
|
92
|
+
table.add_data_column(
|
93
|
+
result['column_name'].to_sym,
|
94
|
+
Type.lookup_internal(result['validator']),
|
95
|
+
result['index_name'].try(:to_sym)
|
96
|
+
)
|
97
|
+
end
|
88
98
|
end
|
89
99
|
end
|
90
100
|
end
|
@@ -37,7 +37,7 @@ module Cequel
|
|
37
37
|
"Can't change type of key column #{old_key.name} from #{old_key.type} to #{new_key.type}"
|
38
38
|
end
|
39
39
|
if old_key.name != new_key.name
|
40
|
-
updater.rename_column(old_key.name, new_key.name)
|
40
|
+
updater.rename_column(old_key.name || :column1, new_key.name)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -64,6 +64,9 @@ module Cequel
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def update_column(old_column, new_column)
|
67
|
+
if old_column.name != new_column.name
|
68
|
+
updater.rename_column(old_column.name || :value, new_column.name)
|
69
|
+
end
|
67
70
|
if old_column.type != new_column.type
|
68
71
|
updater.change_column(new_column.name, new_column.type)
|
69
72
|
end
|
@@ -99,11 +102,15 @@ module Cequel
|
|
99
102
|
end
|
100
103
|
|
101
104
|
def each_column_pair(&block)
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
105
|
+
if existing.compact_storage? && existing.clustering_columns.any?
|
106
|
+
yield existing.data_columns.first, updated.data_columns.first
|
107
|
+
else
|
108
|
+
old_columns = existing.data_columns.index_by { |col| col.name }
|
109
|
+
new_columns = updated.data_columns.index_by { |col| col.name }
|
110
|
+
all_column_names = (old_columns.keys + new_columns.keys).tap(&:uniq!)
|
111
|
+
all_column_names.each do |name|
|
112
|
+
yield old_columns[name], new_columns[name]
|
113
|
+
end
|
107
114
|
end
|
108
115
|
end
|
109
116
|
|
data/lib/cequel/version.rb
CHANGED
@@ -18,6 +18,21 @@ describe Cequel::Record::Associations do
|
|
18
18
|
belongs_to :blog
|
19
19
|
key :id, :uuid, auto: true
|
20
20
|
column :title, :text
|
21
|
+
|
22
|
+
has_many :comments, dependent: :destroy
|
23
|
+
has_many :attachments, dependent: :delete
|
24
|
+
end
|
25
|
+
|
26
|
+
model :Comment do
|
27
|
+
belongs_to :post
|
28
|
+
key :id, :uuid, auto: true
|
29
|
+
column :content, :text
|
30
|
+
end
|
31
|
+
|
32
|
+
model :Attachment do
|
33
|
+
belongs_to :post
|
34
|
+
key :id, :uuid, auto: true
|
35
|
+
column :caption, :text
|
21
36
|
end
|
22
37
|
|
23
38
|
describe '::belongs_to' do
|
@@ -114,6 +129,79 @@ describe Cequel::Record::Associations do
|
|
114
129
|
posts.first.destroy
|
115
130
|
blog.posts(true).map(&:title).should == ['Post 1', 'Post 2']
|
116
131
|
end
|
117
|
-
end
|
118
132
|
|
133
|
+
it "does not allow invalid :dependent options" do
|
134
|
+
expect {
|
135
|
+
Post.class_eval do
|
136
|
+
has_many :users, dependent: :bar
|
137
|
+
end
|
138
|
+
}.to raise_error(ArgumentError)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "does not allow unrecognized options" do
|
142
|
+
expect {
|
143
|
+
Post.class_eval do
|
144
|
+
has_many :users, bogus: :buffalo
|
145
|
+
end
|
146
|
+
}.to raise_error(ArgumentError)
|
147
|
+
end
|
148
|
+
|
149
|
+
context "with dependent => destroy" do
|
150
|
+
let(:post_with_comments) { posts.first }
|
151
|
+
|
152
|
+
before :each do
|
153
|
+
2.times.map do |i|
|
154
|
+
Comment.new do |comment|
|
155
|
+
comment.content = "cat #{i} is awesome"
|
156
|
+
comment.post = post_with_comments
|
157
|
+
end.tap(&:save)
|
158
|
+
end
|
159
|
+
@callback_count = 0
|
160
|
+
Comment.any_instance.stub(:run_callbacks).with(:destroy) do
|
161
|
+
@callback_count += 1
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
it "deletes all children when destroying the parent" do
|
166
|
+
expect {
|
167
|
+
post_with_comments.destroy
|
168
|
+
}.to change { Comment.count }.by(-2)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "executes :destroy callbacks on the children" do
|
172
|
+
expect {
|
173
|
+
post_with_comments.destroy
|
174
|
+
}.to change { @callback_count }.by(2)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context "with dependent => delete" do
|
179
|
+
let(:post_with_attachments) { posts.first }
|
180
|
+
|
181
|
+
before :each do
|
182
|
+
2.times.map do |i|
|
183
|
+
Attachment.new do |comment|
|
184
|
+
comment.caption = "cat #{i} is awesome"
|
185
|
+
comment.post = post_with_attachments
|
186
|
+
end.tap(&:save)
|
187
|
+
end
|
188
|
+
@callback_count = 0
|
189
|
+
Attachment.any_instance.stub(:run_callbacks).with(:destroy) do
|
190
|
+
@callback_count += 1
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
it "deletes all children when destroying the parent" do
|
195
|
+
expect {
|
196
|
+
post_with_attachments.destroy
|
197
|
+
}.to change { Attachment.count }.by(-2)
|
198
|
+
end
|
199
|
+
|
200
|
+
it "executes :destroy callbacks on the children" do
|
201
|
+
expect {
|
202
|
+
post_with_attachments.destroy
|
203
|
+
}.to change { @callback_count }.by(0)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
119
207
|
end
|
@@ -1,45 +1,88 @@
|
|
1
1
|
require File.expand_path('../spec_helper', __FILE__)
|
2
2
|
|
3
3
|
describe Cequel::Record::Schema do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
let(:model) do
|
8
|
-
Class.new do
|
9
|
-
include Cequel::Record
|
10
|
-
self.table_name = 'posts'
|
11
|
-
|
12
|
-
key :permalink, :text
|
13
|
-
column :title, :text
|
14
|
-
list :categories, :text
|
15
|
-
set :tags, :text
|
16
|
-
map :trackbacks, :timestamp, :text
|
17
|
-
table_property :comment, 'Blog Posts'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'new model with simple primary key' do
|
22
|
-
before { model.synchronize_schema }
|
4
|
+
context 'CQL3 table' do
|
5
|
+
after { cequel.schema.drop_table(:posts) }
|
6
|
+
subject { cequel.schema.read_table(:posts) }
|
23
7
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
its(:data_columns) { should include(Cequel::Schema::Map.new(:trackbacks, :timestamp, :text)) }
|
29
|
-
specify { subject.property(:comment).should == 'Blog Posts' }
|
30
|
-
end
|
8
|
+
let(:model) do
|
9
|
+
Class.new do
|
10
|
+
include Cequel::Record
|
11
|
+
self.table_name = 'posts'
|
31
12
|
|
32
|
-
context 'existing model with additional attribute' do
|
33
|
-
before do
|
34
|
-
cequel.schema.create_table :posts do
|
35
13
|
key :permalink, :text
|
36
14
|
column :title, :text
|
37
15
|
list :categories, :text
|
38
16
|
set :tags, :text
|
17
|
+
map :trackbacks, :timestamp, :text
|
18
|
+
table_property :comment, 'Blog Posts'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'new model with simple primary key' do
|
23
|
+
before { model.synchronize_schema }
|
24
|
+
|
25
|
+
its(:partition_key_columns) { should == [Cequel::Schema::Column.new(:permalink, :text)] }
|
26
|
+
its(:data_columns) { should include(Cequel::Schema::Column.new(:title, :text)) }
|
27
|
+
its(:data_columns) { should include(Cequel::Schema::List.new(:categories, :text)) }
|
28
|
+
its(:data_columns) { should include(Cequel::Schema::Set.new(:tags, :text)) }
|
29
|
+
its(:data_columns) { should include(Cequel::Schema::Map.new(:trackbacks, :timestamp, :text)) }
|
30
|
+
specify { subject.property(:comment).should == 'Blog Posts' }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'existing model with additional attribute' do
|
34
|
+
before do
|
35
|
+
cequel.schema.create_table :posts do
|
36
|
+
key :permalink, :text
|
37
|
+
column :title, :text
|
38
|
+
list :categories, :text
|
39
|
+
set :tags, :text
|
40
|
+
end
|
41
|
+
model.synchronize_schema
|
39
42
|
end
|
40
|
-
|
43
|
+
|
44
|
+
its(:data_columns) { should include(Cequel::Schema::Map.new(:trackbacks, :timestamp, :text)) }
|
41
45
|
end
|
46
|
+
end
|
42
47
|
|
43
|
-
|
48
|
+
context 'wide-row legacy table' do
|
49
|
+
let(:legacy_model) do
|
50
|
+
Class.new do
|
51
|
+
include Cequel::Record
|
52
|
+
self.table_name = 'legacy_posts'
|
53
|
+
|
54
|
+
key :blog_subdomain, :text
|
55
|
+
key :id, :uuid
|
56
|
+
column :data, :text
|
57
|
+
|
58
|
+
compact_storage
|
59
|
+
end
|
60
|
+
end
|
61
|
+
after { cequel.schema.drop_table(:legacy_posts) }
|
62
|
+
subject { cequel.schema.read_table(:legacy_posts) }
|
63
|
+
|
64
|
+
context 'new model' do
|
65
|
+
before { legacy_model.synchronize_schema }
|
66
|
+
|
67
|
+
its(:partition_key_columns) { should == [Cequel::Schema::Column.new(:blog_subdomain, :text)] }
|
68
|
+
its(:clustering_columns) { should == [Cequel::Schema::Column.new(:id, :uuid)] }
|
69
|
+
it { should be_compact_storage }
|
70
|
+
its(:data_columns) { should == [Cequel::Schema::Column.new(:data, :text)] }
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'existing model' do
|
74
|
+
before do
|
75
|
+
legacy_connection.execute(<<-CQL2)
|
76
|
+
CREATE COLUMNFAMILY legacy_posts (blog_subdomain text PRIMARY KEY)
|
77
|
+
WITH comparator=uuid AND default_validation=text
|
78
|
+
CQL2
|
79
|
+
legacy_model.synchronize_schema
|
80
|
+
end
|
81
|
+
|
82
|
+
its(:partition_key_columns) { should == [Cequel::Schema::Column.new(:blog_subdomain, :text)] }
|
83
|
+
its(:clustering_columns) { should == [Cequel::Schema::Column.new(:id, :uuid)] }
|
84
|
+
it { should be_compact_storage }
|
85
|
+
its(:data_columns) { should == [Cequel::Schema::Column.new(:data, :text)] }
|
86
|
+
end
|
44
87
|
end
|
45
88
|
end
|
@@ -304,25 +304,86 @@ describe Cequel::Schema::TableReader do
|
|
304
304
|
table.property(:compression)[:crc_check_chance].should == 0.5
|
305
305
|
end
|
306
306
|
|
307
|
-
|
307
|
+
it 'should recognize no compact storage' do
|
308
|
+
table.should_not be_compact_storage
|
309
|
+
end
|
308
310
|
|
309
|
-
describe '
|
311
|
+
end # describe 'reading storage properties'
|
310
312
|
|
311
|
-
|
313
|
+
describe 'skinny-row compact storage' do
|
314
|
+
before do
|
312
315
|
cequel.execute <<-CQL
|
313
|
-
CREATE TABLE posts (permalink text PRIMARY KEY, body text)
|
316
|
+
CREATE TABLE posts (permalink text PRIMARY KEY, title text, body text)
|
317
|
+
WITH COMPACT STORAGE
|
314
318
|
CQL
|
315
|
-
table.should_not be_compact_storage
|
316
319
|
end
|
320
|
+
subject { table }
|
321
|
+
|
322
|
+
it { should be_compact_storage }
|
323
|
+
its(:partition_key_columns) { should ==
|
324
|
+
[Cequel::Schema::PartitionKey.new(:permalink, :text)] }
|
325
|
+
its(:clustering_columns) { should be_empty }
|
326
|
+
its(:data_columns) { should =~
|
327
|
+
[Cequel::Schema::DataColumn.new(:title, :text),
|
328
|
+
Cequel::Schema::DataColumn.new(:body, :text)] }
|
329
|
+
end
|
317
330
|
|
318
|
-
|
331
|
+
describe 'wide-row compact storage' do
|
332
|
+
before do
|
319
333
|
cequel.execute <<-CQL
|
320
|
-
CREATE TABLE posts (
|
334
|
+
CREATE TABLE posts (
|
335
|
+
blog_subdomain text,
|
336
|
+
id uuid,
|
337
|
+
data text,
|
338
|
+
PRIMARY KEY (blog_subdomain, id)
|
339
|
+
)
|
321
340
|
WITH COMPACT STORAGE
|
322
341
|
CQL
|
323
|
-
table.should be_compact_storage
|
324
342
|
end
|
343
|
+
subject { table }
|
344
|
+
|
345
|
+
it { should be_compact_storage }
|
346
|
+
its(:partition_key_columns) { should ==
|
347
|
+
[Cequel::Schema::PartitionKey.new(:blog_subdomain, :text)] }
|
348
|
+
its(:clustering_columns) { should ==
|
349
|
+
[Cequel::Schema::ClusteringColumn.new(:id, :uuid)] }
|
350
|
+
its(:data_columns) { should ==
|
351
|
+
[Cequel::Schema::DataColumn.new(:data, :text)] }
|
352
|
+
end
|
325
353
|
|
354
|
+
describe 'skinny-row legacy table' do
|
355
|
+
before do
|
356
|
+
legacy_connection.execute <<-CQL
|
357
|
+
CREATE TABLE posts (permalink text PRIMARY KEY, title text, body text)
|
358
|
+
CQL
|
359
|
+
end
|
360
|
+
subject { table }
|
361
|
+
|
362
|
+
it { should be_compact_storage }
|
363
|
+
its(:partition_key_columns) { should ==
|
364
|
+
[Cequel::Schema::PartitionKey.new(:permalink, :text)] }
|
365
|
+
its(:clustering_columns) { should be_empty }
|
366
|
+
its(:data_columns) { should =~
|
367
|
+
[Cequel::Schema::DataColumn.new(:title, :text),
|
368
|
+
Cequel::Schema::DataColumn.new(:body, :text)] }
|
369
|
+
end
|
370
|
+
|
371
|
+
describe 'wide-row legacy table' do
|
372
|
+
before do
|
373
|
+
legacy_connection.execute(<<-CQL2)
|
374
|
+
CREATE COLUMNFAMILY posts (blog_subdomain text PRIMARY KEY)
|
375
|
+
WITH comparator=uuid AND default_validation=text
|
376
|
+
CQL2
|
377
|
+
end
|
378
|
+
subject { table }
|
379
|
+
|
380
|
+
it { should be_compact_storage }
|
381
|
+
its(:partition_key_columns) { should ==
|
382
|
+
[Cequel::Schema::PartitionKey.new(:blog_subdomain, :text)] }
|
383
|
+
its(:clustering_columns) { should ==
|
384
|
+
[Cequel::Schema::ClusteringColumn.new(nil, :uuid)] }
|
385
|
+
its(:data_columns) { should ==
|
386
|
+
[Cequel::Schema::DataColumn.new(nil, :text)] }
|
326
387
|
end
|
327
388
|
|
328
389
|
end
|
data/spec/support/helpers.rb
CHANGED
@@ -52,8 +52,9 @@ module Cequel
|
|
52
52
|
|
53
53
|
def self.cequel
|
54
54
|
@cequel ||= Cequel.connect(
|
55
|
-
:
|
56
|
-
:
|
55
|
+
host: host,
|
56
|
+
keyspace: keyspace_name,
|
57
|
+
thrift: {retries: 5, cached_connections: true}
|
57
58
|
).tap do |cequel|
|
58
59
|
cequel.logger = Logger.new(STDOUT) if ENV['CEQUEL_LOG_QUERIES']
|
59
60
|
end
|
@@ -67,10 +68,22 @@ module Cequel
|
|
67
68
|
ENV['CEQUEL_TEST_KEYSPACE'] || 'cequel_test'
|
68
69
|
end
|
69
70
|
|
71
|
+
def self.legacy_connection
|
72
|
+
@legacy_connection ||= CassandraCQL::Database.new(
|
73
|
+
Cequel::SpecSupport::Helpers.host,
|
74
|
+
:keyspace => Cequel::SpecSupport::Helpers.keyspace_name,
|
75
|
+
:cql_version => '2.0.0'
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
70
79
|
def cequel
|
71
80
|
Helpers.cequel
|
72
81
|
end
|
73
82
|
|
83
|
+
def legacy_connection
|
84
|
+
Helpers.legacy_connection
|
85
|
+
end
|
86
|
+
|
74
87
|
def max_statements!(number)
|
75
88
|
cequel.should_receive(:execute).at_most(number).times.and_call_original
|
76
89
|
end
|
metadata
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.
|
4
|
+
version: 1.0.0.pre.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Brown
|
8
8
|
- Aubrey Holland
|
9
9
|
- Keenan Brock
|
10
10
|
- Insoo Buzz Jung
|
11
|
+
- Louis Simoneau
|
11
12
|
autorequire:
|
12
13
|
bindir: bin
|
13
14
|
cert_chain: []
|
14
|
-
date: 2013-09-
|
15
|
+
date: 2013-09-30 00:00:00.000000000 Z
|
15
16
|
dependencies:
|
16
17
|
- !ruby/object:Gem::Dependency
|
17
18
|
name: activesupport
|