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.
@@ -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
- before :each do
78
- @account = Account.create(:name => "Involved Pty. Ltd.")
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
- it "should have a token field" do
94
- @account.attributes.include?('token').should == true
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
- it "should have a token of correct length" do
100
- @account.token.length.should == 16
101
- @link.token.length.should == 3
102
- @video.vid.length.should == 8
103
- @image.token.length.should == 8
104
- end
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
- it "should only generate unique tokens" do
107
- Link.create_indexes
108
- 1000.times do
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
- it "should have a token containing only the specified characters" do
115
- 50.times do
116
- @account = Account.create(:name => "Smith & Co. LLC")
117
- @person = Person.create(:email => "some_random_235@gmail.com")
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
- 50.times do
124
- @link = Link.create(:url => "http://involved.com.au")
125
- @link.token.gsub(/[A-Za-z0-9]/, "").length.should == 0
126
- end
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
- 50.times do |index|
129
- @video = Video.create(:name => "A test video")
130
- @video.vid.gsub(/[A-Za-z]/, "").length.should == 0
131
- end
132
-
133
- 50.times do |index|
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
- it "should create the only after the first save" do
140
- @account = Account.new(:name => "Smith & Co. LLC")
141
- @account.token.should be_nil
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
- it "should return the token as its parameter" do
150
- @account.to_param.should == @account.token
151
- @link.to_param.should == @link.token
152
- @video.to_param.should == @video.vid
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
- it "should be findable by token" do
157
- 50.times do |index|
158
- Account.create(:name => "A random company #{index}")
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
- 10.times do |index|
164
- Video.create(:name => "Lord of the Rings, Super Special Edition part #{index}")
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
- it "should fail with an exception after 3 retries" do
177
- Link.destroy_all
178
- Link.create_indexes
179
-
180
- @first_link = Link.create(:url => "http://involved.com.au")
181
- Link.any_instance.stub(:generate_token).and_return(@first_link.token)
182
- @link = Link.new(:url => "http://fail.com")
183
-
184
- expect { @link.save! }.to raise_error(Mongoid::Token::CollisionRetriesExceeded)
185
-
186
- Link.count.should == 1
187
- Link.where(:token => @first_link.token).count.should == 1
188
- end
189
-
190
- it "tries to resolve collisions when instantiated with create!" do
191
- link = Link.create!(url: "http://example.com/1")
192
-
193
- Link.any_instance.stub(:generate_token).and_return(link.token)
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
- expect { Link.create!(url: "http://example.com/2") }.to raise_error(Mongoid::Token::CollisionRetriesExceeded)
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
- it "should not raise a custom error if an operation failure is thrown for another reason" do
199
- link = Link.new
200
- lambda{ link.save! }.should_not raise_error(Mongoid::Token::CollisionRetriesExceeded)
201
- link.valid?.should == false
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
- it "should not raise a custom exception if retries are set to zero" do
205
- FailLink.destroy_all
206
- FailLink.create_indexes
207
-
208
- @first_link = FailLink.create(:url => "http://involved.com.au")
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
- it "should create unique indexes on embedded documents" do
216
- @cluster = Cluster.create(:name => "CLUSTER_001")
217
- 5.times do |index|
218
- @cluster.nodes.create!(:name => "NODE_#{index.to_s.rjust(3, '0')}")
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
- @cluster.nodes.each do |node|
222
- node.attributes.include?('token').should == true
223
- node.token.match(/[0-9]{8}/).should_not == nil
224
- end
225
- end
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
- describe "with :fixed_numeric_not_null" do
228
- it "should not start with 0" do
229
- 1000.times do
230
- image = Image.create(:url => "http://something.com/image.png")
231
- image.token.should_not start_with "0"
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: 1.1.1
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-02-18 00:00:00.000000000 Z
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