mongoid_token 1.1.1 → 2.0.0
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.
- data/.autotest +0 -1
- data/README.md +147 -77
- data/lib/mongoid/token/collision_resolver.rb +37 -0
- data/lib/mongoid/token/collisions.rb +31 -0
- data/lib/mongoid/token/finders.rb +19 -0
- data/lib/mongoid/token/generator.rb +72 -0
- data/lib/mongoid/token/options.rb +68 -0
- data/lib/mongoid/token.rb +63 -0
- data/lib/mongoid_token.rb +1 -116
- data/lib/version.rb +1 -1
- data/spec/mongoid/token/collisions_spec.rb +92 -0
- data/spec/mongoid/token/exceptions_spec.rb +4 -0
- data/spec/mongoid/token/finders_spec.rb +41 -0
- data/spec/mongoid/token/generator_spec.rb +49 -0
- data/spec/mongoid/token/options_spec.rb +70 -0
- data/spec/mongoid/token_spec.rb +183 -200
- data/spec/spec_helper.rb +5 -1
- metadata +18 -2
data/spec/mongoid/token_spec.rb
CHANGED
@@ -1,235 +1,218 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
2
|
|
3
|
-
class Account
|
4
|
-
include Mongoid::Document
|
5
|
-
include Mongoid::Token
|
6
|
-
field :name
|
7
|
-
token :length => 16, :contains => :fixed_numeric
|
8
|
-
end
|
9
|
-
|
10
|
-
class Person
|
11
|
-
include Mongoid::Document
|
12
|
-
include Mongoid::Token
|
13
|
-
field :email
|
14
|
-
token :length => 6, :contains => :numeric
|
15
|
-
end
|
16
|
-
|
17
|
-
class Link
|
18
|
-
include Mongoid::Document
|
19
|
-
include Mongoid::Token
|
20
|
-
|
21
|
-
field :url
|
22
|
-
token :length => 3, :contains => :alphanumeric
|
23
|
-
|
24
|
-
validates :url, :presence => true
|
25
|
-
end
|
26
|
-
|
27
|
-
class FailLink
|
28
|
-
include Mongoid::Document
|
29
|
-
include Mongoid::Token
|
30
|
-
field :url
|
31
|
-
token :length => 3, :contains => :alphanumeric, :retry => 0
|
32
|
-
end
|
33
|
-
|
34
|
-
class Video
|
35
|
-
include Mongoid::Document
|
36
|
-
include Mongoid::Token
|
37
|
-
|
38
|
-
field :name
|
39
|
-
token :length => 8, :contains => :alpha, :field_name => :vid
|
40
|
-
end
|
41
|
-
|
42
|
-
class Image
|
43
|
-
include Mongoid::Document
|
44
|
-
include Mongoid::Token
|
45
|
-
|
46
|
-
field :url
|
47
|
-
token :length => 8, :contains => :fixed_numeric_no_leading_zeros
|
48
|
-
end
|
49
|
-
|
50
|
-
class Event
|
51
|
-
include Mongoid::Document
|
52
|
-
include Mongoid::Token
|
53
|
-
|
54
|
-
field :name
|
55
|
-
token :length => 8, :contains => :alpha_lower
|
56
|
-
end
|
57
|
-
|
58
|
-
class Node
|
59
|
-
include Mongoid::Document
|
60
|
-
include Mongoid::Token
|
61
|
-
|
62
|
-
field :name
|
63
|
-
token :length => 8, :contains => :fixed_numeric
|
64
|
-
|
65
|
-
embedded_in :cluster
|
66
|
-
end
|
67
|
-
|
68
|
-
class Cluster
|
69
|
-
include Mongoid::Document
|
70
|
-
|
71
|
-
field :name
|
72
|
-
|
73
|
-
embeds_many :nodes
|
74
|
-
end
|
75
|
-
|
76
3
|
describe Mongoid::Token do
|
77
|
-
|
78
|
-
|
79
|
-
@link = Link.create(:url => "http://involved.com.au")
|
80
|
-
@video = Video.create(:name => "Nyan nyan")
|
81
|
-
@image = Image.create(:url => "http://involved.com.au/image.png")
|
82
|
-
@event = Event.create(:name => "Super cool party!")
|
83
|
-
|
84
|
-
Account.create_indexes
|
85
|
-
Link.create_indexes
|
86
|
-
FailLink.create_indexes
|
87
|
-
Video.create_indexes
|
88
|
-
Image.create_indexes
|
89
|
-
Event.create_indexes
|
90
|
-
Node.create_indexes
|
4
|
+
let(:document_class) do
|
5
|
+
Class.new(Document)
|
91
6
|
end
|
92
7
|
|
93
|
-
|
94
|
-
|
95
|
-
@link.attributes.include?('token').should == true
|
96
|
-
@video.attributes.include?('vid').should == true
|
8
|
+
let(:document) do
|
9
|
+
document_class.create
|
97
10
|
end
|
98
11
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
12
|
+
describe "#token" do
|
13
|
+
describe "field" do
|
14
|
+
before(:each) { document_class.send(:token) }
|
15
|
+
it "should be created" do
|
16
|
+
expect(document).to have_field(:token)
|
17
|
+
end
|
105
18
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
@link = Link.create(:url => "http://involved.com.au")
|
110
|
-
Link.where(:token => @link.token).count.should == 1
|
19
|
+
it "should be indexed" do
|
20
|
+
expect(document).to have_index_for(:token => 1).with_options(:unique => true)
|
21
|
+
end
|
111
22
|
end
|
112
|
-
end
|
113
23
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
@account.token.gsub(/[0-9]/, "").length.should == 0
|
120
|
-
@person.token.gsub(/[0-9]/, "").length.should == 0
|
121
|
-
end
|
24
|
+
describe "options" do
|
25
|
+
it "should accept custom field names" do
|
26
|
+
document_class.send(:token, :field_name => :smells_as_sweet)
|
27
|
+
expect(document).to have_field(:smells_as_sweet)
|
28
|
+
end
|
122
29
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
30
|
+
it "should accept custom lengths" do
|
31
|
+
document_class.send(:token, :length => 13)
|
32
|
+
expect(document.token.length).to eq 13
|
33
|
+
end
|
127
34
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
@event = Event.create(:name => "Super cool party!2")
|
135
|
-
@event.token.gsub(/[a-z]/, "").length.should == 0
|
136
|
-
end
|
137
|
-
end
|
35
|
+
it "should disable custom finders" do
|
36
|
+
class UntaintedDocument
|
37
|
+
include Mongoid::Document
|
38
|
+
include Mongoid::Token
|
39
|
+
end
|
40
|
+
dc = Class.new(UntaintedDocument)
|
138
41
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
@account.save!
|
143
|
-
@account.token.should_not be_nil
|
144
|
-
initial_token = @account.token
|
145
|
-
@account.save!
|
146
|
-
initial_token.should == @account.token
|
147
|
-
end
|
42
|
+
dc.send(:token, :skip_finders => true)
|
43
|
+
expect(dc.public_methods).to_not include(:find_with_token)
|
44
|
+
end
|
148
45
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
46
|
+
it "should disable `to_param` overrides" do
|
47
|
+
document_class.send(:token, :override_to_param => false)
|
48
|
+
expect(document.to_param).to_not eq document.token
|
49
|
+
end
|
154
50
|
|
51
|
+
describe "contains" do
|
52
|
+
context "with :alphanumeric" do
|
53
|
+
it "should contain only letters and numbers" do
|
54
|
+
document_class.send(:token, :contains => :alphanumeric, :length => 64)
|
55
|
+
expect(document.token).to match(/[A-Za-z0-9]{64}/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
context "with :alpha" do
|
59
|
+
it "should contain only letters" do
|
60
|
+
document_class.send(:token, :contains => :alpha, :length => 64)
|
61
|
+
expect(document.token).to match(/[A-Za-z]{64}/)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
context "with :alpha_upper" do
|
65
|
+
it "should contain only uppercase letters" do
|
66
|
+
document_class.send(:token, :contains => :alpha_upper, :length => 64)
|
67
|
+
expect(document.token).to match(/[A-Z]{64}/)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
context "with :alpha_lower" do
|
71
|
+
it "should contain only lowercase letters" do
|
72
|
+
document_class.send(:token, :contains => :alpha_lower, :length => 64)
|
73
|
+
expect(document.token).to match(/[a-z]{64}/)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
context "with :numeric" do
|
77
|
+
it "should only contain numbers" do
|
78
|
+
document_class.send(:token, :contains => :numeric, :length => 64)
|
79
|
+
expect(document.token).to match(/[0-9]{1,64}/)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
context "with :fixed_numeric" do
|
83
|
+
it "should contain only numbers and be a fixed-length" do
|
84
|
+
document_class.send(:token, :contains => :fixed_numeric, :length => 64)
|
85
|
+
expect(document.token).to match(/[0-9]{64}/)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
context "with :fixed_numeric_no_leading_zeros" do
|
89
|
+
it "should contain only numbers, be a fixed length, and have no leading zeros" do
|
90
|
+
document_class.send(:token, :contains => :fixed_numeric_no_leading_zeros, :length => 64)
|
91
|
+
expect(document.token).to match(/[1-9]{1}[0-9]{63}/)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
155
95
|
|
156
|
-
|
157
|
-
|
158
|
-
|
96
|
+
describe "pattern" do
|
97
|
+
it "should conform" do
|
98
|
+
document_class.send(:token, :pattern => "%d%d%d%d%C%C%C%C")
|
99
|
+
expect(document.token).to match(/[0-9]{4}[A-Z]{4}/)
|
100
|
+
end
|
101
|
+
context "when there's a static prefix" do
|
102
|
+
it "should start with the prefix" do
|
103
|
+
document_class.send(:token, :pattern => "PREFIX-%d%d%d%d")
|
104
|
+
expect(document.token).to match(/PREFIX\-[0-9]{4}/)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
context "when there's an infix" do
|
108
|
+
it "should contain the infix" do
|
109
|
+
document_class.send(:token, :pattern => "%d%d%d%d-INFIX-%d%d%d%d")
|
110
|
+
expect(document.token).to match(/[0-9]{4}\-INFIX\-[0-9]{4}/)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
context "when there's a suffix" do
|
114
|
+
it "should end with the suffix" do
|
115
|
+
document_class.send(:token, :pattern => "%d%d%d%d-SUFFIX")
|
116
|
+
expect(document.token).to match(/[0-9]{4}\-SUFFIX/)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
159
120
|
end
|
160
|
-
Account.find_by_token(@account.token).id.should == @account.id
|
161
|
-
Account.find_by_token(Account.last.token).id.should == Account.last.id
|
162
121
|
|
163
|
-
|
164
|
-
|
122
|
+
it "should allow for multiple tokens of different names" do
|
123
|
+
document_class.send(:token, :contains => :alpha_upper)
|
124
|
+
document_class.send(:token, :field_name => :sharing_id, :contains => :alpha_lower)
|
125
|
+
expect(document.token).to match(/[A-Z]{4}/)
|
126
|
+
expect(document.sharing_id).to match(/[a-z]{4}/)
|
165
127
|
end
|
166
|
-
Video.find_by_token(@video.vid).id.should == @video.id
|
167
|
-
Video.find_by_token(Video.last.vid).id.should == Video.last.id
|
168
|
-
end
|
169
|
-
|
170
|
-
it "should create a token, if the token is missing" do
|
171
|
-
@account.token = nil
|
172
|
-
@account.save!
|
173
|
-
@account.token.should_not be_nil
|
174
128
|
end
|
175
129
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
130
|
+
describe "callbacks" do
|
131
|
+
context "when the document is a new record" do
|
132
|
+
let(:document){ document_class.new }
|
133
|
+
it "should create the token after being saved" do
|
134
|
+
document_class.send(:token)
|
135
|
+
expect(document.token).to be_nil
|
136
|
+
document.save
|
137
|
+
expect(document.token).to_not be_nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
context "when the document is not a new record" do
|
141
|
+
it "should not change the token after being saved" do
|
142
|
+
document_class.send(:token)
|
143
|
+
token_before = document.token
|
144
|
+
document.save
|
145
|
+
expect(document.token).to eq token_before
|
146
|
+
end
|
147
|
+
context "and the token is nil" do
|
148
|
+
it "should create a new token after being saved" do
|
149
|
+
document_class.send(:token)
|
150
|
+
token_before = document.token
|
151
|
+
document.token = nil
|
152
|
+
document.save
|
153
|
+
expect(document.token).to_not be_nil
|
154
|
+
expect(document.token).to_not eq token_before
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
context "when the document is cloned" do
|
159
|
+
it "should set the token to nil" do
|
160
|
+
document.class.send(:token, :length => 64, :contains => :alpha_upper)
|
161
|
+
d2 = document.clone
|
162
|
+
expect(d2.token).to be_nil
|
163
|
+
end
|
194
164
|
|
195
|
-
|
165
|
+
it "should generate a new token with the same options as the source document" do
|
166
|
+
document.class.send(:token, :length => 64, :contains => :alpha_upper)
|
167
|
+
d2 = document.clone
|
168
|
+
d2.save
|
169
|
+
expect(d2.token).to_not eq document.token
|
170
|
+
expect(d2.token).to match(/[A-Z]{64}/)
|
171
|
+
end
|
172
|
+
end
|
196
173
|
end
|
197
174
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
175
|
+
describe "finders" do
|
176
|
+
it "should create a custom find method" do
|
177
|
+
document_class.send(:token, :field_name => :other_token)
|
178
|
+
expect(document.class.public_methods).to include(:find_by_other_token)
|
179
|
+
end
|
202
180
|
end
|
203
181
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
Link.any_instance.stub(:generate_token).and_return(@first_link.token)
|
210
|
-
@link = FailLink.new(:url => "http://fail.com")
|
211
|
-
|
212
|
-
lambda{ @link.save! }.should_not raise_error(Mongoid::Token::CollisionRetriesExceeded)
|
182
|
+
describe ".to_param" do
|
183
|
+
it "should return the token" do
|
184
|
+
document_class.send(:token)
|
185
|
+
expect(document.to_param).to eq document.token
|
186
|
+
end
|
213
187
|
end
|
214
188
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
189
|
+
describe "collision resolution" do
|
190
|
+
before(:each) do
|
191
|
+
document_class.send(:token)
|
192
|
+
document_class.create_indexes
|
219
193
|
end
|
220
194
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
195
|
+
context "when creating a new record" do
|
196
|
+
it "should raise an exception when collisions can't be resolved on save" do
|
197
|
+
document.token = "1234"
|
198
|
+
document.save
|
199
|
+
d2 = document.clone
|
200
|
+
d2.stub(:generate_token).and_return("1234")
|
201
|
+
expect{d2.save}.to raise_exception(Mongoid::Token::CollisionRetriesExceeded)
|
202
|
+
end
|
226
203
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
204
|
+
it "should raise an exception when collisions can't be resolved on create!" do
|
205
|
+
document.token = "1234"
|
206
|
+
document.save
|
207
|
+
document_class.any_instance.stub(:generate_token).and_return("1234")
|
208
|
+
expect{document_class.create!}.to raise_exception(Mongoid::Token::CollisionRetriesExceeded)
|
232
209
|
end
|
233
210
|
end
|
211
|
+
|
212
|
+
it "should not raise a custom error if an operation failure is thrown for another reason" do
|
213
|
+
document_class.send(:field, :name)
|
214
|
+
document_class.send(:validates_presence_of, :name)
|
215
|
+
expect{document_class.create!}.to_not raise_exception(Mongoid::Token::CollisionRetriesExceeded)
|
216
|
+
end
|
234
217
|
end
|
235
218
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,10 +4,14 @@ require 'database_cleaner'
|
|
4
4
|
require 'mongoid'
|
5
5
|
require 'mongoid-rspec'
|
6
6
|
require 'mongoid_token'
|
7
|
-
require 'mongoid/token/exceptions'
|
8
7
|
|
9
8
|
ENV['MONGOID_ENV'] = "test"
|
10
9
|
|
10
|
+
class Document
|
11
|
+
include Mongoid::Document
|
12
|
+
include Mongoid::Token
|
13
|
+
end
|
14
|
+
|
11
15
|
RSpec.configure do |config|
|
12
16
|
config.include Mongoid::Matchers
|
13
17
|
config.before(:suite) do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid_token
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongoid
|
@@ -43,11 +43,22 @@ files:
|
|
43
43
|
- README.md
|
44
44
|
- Rakefile
|
45
45
|
- benchmarks/benchmark.rb
|
46
|
+
- lib/mongoid/token.rb
|
47
|
+
- lib/mongoid/token/collision_resolver.rb
|
48
|
+
- lib/mongoid/token/collisions.rb
|
46
49
|
- lib/mongoid/token/exceptions.rb
|
50
|
+
- lib/mongoid/token/finders.rb
|
51
|
+
- lib/mongoid/token/generator.rb
|
52
|
+
- lib/mongoid/token/options.rb
|
47
53
|
- lib/mongoid_token.rb
|
48
54
|
- lib/version.rb
|
49
55
|
- mongoid_token.gemspec
|
50
56
|
- spec/mongoid.yml
|
57
|
+
- spec/mongoid/token/collisions_spec.rb
|
58
|
+
- spec/mongoid/token/exceptions_spec.rb
|
59
|
+
- spec/mongoid/token/finders_spec.rb
|
60
|
+
- spec/mongoid/token/generator_spec.rb
|
61
|
+
- spec/mongoid/token/options_spec.rb
|
51
62
|
- spec/mongoid/token_spec.rb
|
52
63
|
- spec/spec_helper.rb
|
53
64
|
homepage: http://github.com/thetron/mongoid_token
|
@@ -76,5 +87,10 @@ specification_version: 3
|
|
76
87
|
summary: A little random, unique token generator for Mongoid documents.
|
77
88
|
test_files:
|
78
89
|
- spec/mongoid.yml
|
90
|
+
- spec/mongoid/token/collisions_spec.rb
|
91
|
+
- spec/mongoid/token/exceptions_spec.rb
|
92
|
+
- spec/mongoid/token/finders_spec.rb
|
93
|
+
- spec/mongoid/token/generator_spec.rb
|
94
|
+
- spec/mongoid/token/options_spec.rb
|
79
95
|
- spec/mongoid/token_spec.rb
|
80
96
|
- spec/spec_helper.rb
|