unique_generator 0.0.1
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/.gitignore +4 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +8 -0
- data/Rakefile +13 -0
- data/lib/unique_generator/version.rb +3 -0
- data/lib/unique_generator.rb +78 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/specific/active_record_spec.rb +14 -0
- data/spec/specific/mongo_mapper_spec.rb +19 -0
- data/spec/support/reversible_data_setup.rb +9 -0
- data/spec/support/shared_unique_specs.rb +78 -0
- data/spec/unique_generator_spec.rb +9 -0
- data/unique_generator.gemspec +27 -0
- metadata +132 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3@unique_generate --create
|
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require "unique_generator/version"
|
2
|
+
require "active_support/concern"
|
3
|
+
|
4
|
+
module UniqueGenerator
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def self.setup!
|
8
|
+
ActiveRecord::Base.send(:include, self) if defined?(ActiveRecord::Base)
|
9
|
+
MongoMapper::Document.plugin(self) if defined?(MongoMapper::Document)
|
10
|
+
end
|
11
|
+
setup!
|
12
|
+
|
13
|
+
CHOICES = (Array('A'..'Z') + Array('a'..'z') + Array('0'..'9'))
|
14
|
+
|
15
|
+
included do
|
16
|
+
if defined?(ActiveRecord::Base) && self <= ActiveRecord::Base
|
17
|
+
include UniqueChecks::AR
|
18
|
+
elsif defined?(MongoMapper::Document) && self <= MongoMapper::Plugins::Document
|
19
|
+
include UniqueChecks::MM
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module UniqueChecks
|
24
|
+
|
25
|
+
module MM
|
26
|
+
# Returns whether or not the given field is unique to every item.
|
27
|
+
def unique_field?(field_name)
|
28
|
+
scope = self.class.where(field_name => send(field_name))
|
29
|
+
scope = scope.where(:_id.ne => id) if id.present?
|
30
|
+
scope.empty?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module AR
|
35
|
+
# Returns whether or not the given field is unique to every item.
|
36
|
+
def unique_field?(field_name)
|
37
|
+
scope = self.class.where(field_name => send(field_name))
|
38
|
+
# When we have an id, check for those with a different id.
|
39
|
+
if id.present?
|
40
|
+
conditions = self.class.scoped.table[:id].eq(id).not
|
41
|
+
scope = scope.where(conditions)
|
42
|
+
end
|
43
|
+
scope.empty?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
module ClassMethods
|
50
|
+
|
51
|
+
# Generate a unique field
|
52
|
+
def generate_unique(length = 32, &blk)
|
53
|
+
unique = generate_random(length)
|
54
|
+
unique = generate_random(length) until blk.call(unique)
|
55
|
+
unique
|
56
|
+
end
|
57
|
+
|
58
|
+
# Generate a random string with the given number of characters.
|
59
|
+
def generate_random(length = 32)
|
60
|
+
(1..length).inject("") { |token, _| token << CHOICES.sample }
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
module InstanceMethods
|
66
|
+
|
67
|
+
# Generate unique field.
|
68
|
+
def generate_unique_field!(name, size = 32)
|
69
|
+
return if send(name).present?
|
70
|
+
self.class.generate_unique(size) do |token|
|
71
|
+
send "#{name}=", token
|
72
|
+
unique_field? name
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
Bundler.require :default, :development
|
5
|
+
|
6
|
+
Dir[Pathname(__FILE__).dirname.join("support", "**", "*.rb")].each { |f| require f }
|
7
|
+
|
8
|
+
UniqueGenerator.setup!
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.mock_with :rr
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UniqueGenerator, 'along side active record' do
|
4
|
+
|
5
|
+
# Temporary environment
|
6
|
+
let(:manager) { ReversibleData.manager_for(:users) }
|
7
|
+
before(:each) { manager.up! }
|
8
|
+
after(:each) { manager.down! }
|
9
|
+
|
10
|
+
let(:example_model) { User }
|
11
|
+
|
12
|
+
it_should_behave_like 'a model with unique generator enabled'
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UniqueGenerator, 'along side mongo mapper' do
|
4
|
+
|
5
|
+
class ExampleModel
|
6
|
+
include MongoMapper::Document
|
7
|
+
include UniqueGenerator
|
8
|
+
|
9
|
+
key :name, String
|
10
|
+
key :token, String
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:example_model) { ExampleModel }
|
15
|
+
after(:each) { ExampleModel.destroy_all }
|
16
|
+
|
17
|
+
it_should_behave_like 'a model with unique generator enabled'
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
shared_examples_for 'a model with unique generator enabled' do
|
2
|
+
|
3
|
+
it 'should include the mixin' do
|
4
|
+
example_model.should be < UniqueGenerator
|
5
|
+
end
|
6
|
+
|
7
|
+
describe 'on an instance of an object' do
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
example_model.create! :name => "Test Name A"
|
11
|
+
example_model.create! :name => "Test Name B"
|
12
|
+
@other_model = example_model.create! :name => "Test Name C"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should let you correctly check if a field has a unique value" do
|
16
|
+
example_model.create(:name => "Test Name A").should_not be_unique_field :name
|
17
|
+
example_model.create(:name => "Test Name D").should be_unique_field :name
|
18
|
+
@other_model.should be_unique_field :name
|
19
|
+
@other_model.name = 'Test Name A'
|
20
|
+
@other_model.should_not be_unique_field :name
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should let you generate a unique token' do
|
25
|
+
model = example_model.new
|
26
|
+
model.token.should be_blank
|
27
|
+
model.generate_unique_field! :token
|
28
|
+
model.token.should be_present
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should let you generate the token length' do
|
32
|
+
model = example_model.new
|
33
|
+
model.generate_unique_field! :token, 100
|
34
|
+
model.token.length.should == 100
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'on a class including the mixin' do
|
40
|
+
|
41
|
+
it 'should add a generate random method' do
|
42
|
+
example_model.should respond_to(:generate_random)
|
43
|
+
example_model.generate_random.should be_present
|
44
|
+
example_model.generate_random.should_not == example_model.generate_random
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should let you specify the random string length' do
|
48
|
+
example_model.generate_random(32).length.should == 32
|
49
|
+
example_model.generate_random(64).length.should == 64
|
50
|
+
example_model.generate_random(16).length.should == 16
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should let you generate a unique value' do
|
54
|
+
example_model.should respond_to(:generate_unique)
|
55
|
+
v = nil
|
56
|
+
example_model.generate_unique do |value|
|
57
|
+
v = value
|
58
|
+
end
|
59
|
+
v.should be_present
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should use generate random until the predicate is true' do
|
63
|
+
times_called = 0
|
64
|
+
mock(example_model).generate_random(32).times(3)
|
65
|
+
example_model.generate_unique do |t|
|
66
|
+
(times_called += 1) == 3
|
67
|
+
end
|
68
|
+
times_called.should == 3
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should let you pass an argument to generate random' do
|
72
|
+
mock(example_model).generate_random(64) { 'Test' }
|
73
|
+
example_model.generate_unique(64) { |t| true }
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "unique_generator/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "unique_generator"
|
7
|
+
s.version = UniqueGenerator::VERSION
|
8
|
+
s.authors = ["Darcy Laycock"]
|
9
|
+
s.email = ["darcy@filtersquad.com"]
|
10
|
+
s.homepage = "http://github.com/filtersquad/unique_generator"
|
11
|
+
s.summary = %q{Makes generating unique fields in MongoMapper and ActiveRecord easy.}
|
12
|
+
s.description = %q{ActiveRecord, MongoMapper and general tools for generating unique values e.g. api keys and tokens.}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_runtime_dependency "activesupport"
|
20
|
+
|
21
|
+
s.add_development_dependency "activerecord"
|
22
|
+
s.add_development_dependency "mongo_mapper"
|
23
|
+
s.add_development_dependency "reversible_data"
|
24
|
+
s.add_development_dependency "rr"
|
25
|
+
s.add_development_dependency "rspec"
|
26
|
+
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: unique_generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Darcy Laycock
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &70246689187780 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70246689187780
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activerecord
|
27
|
+
requirement: &70246689187360 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70246689187360
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: mongo_mapper
|
38
|
+
requirement: &70246689186940 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70246689186940
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: reversible_data
|
49
|
+
requirement: &70246689186520 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70246689186520
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rr
|
60
|
+
requirement: &70246689186100 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70246689186100
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: &70246689202040 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70246689202040
|
80
|
+
description: ActiveRecord, MongoMapper and general tools for generating unique values
|
81
|
+
e.g. api keys and tokens.
|
82
|
+
email:
|
83
|
+
- darcy@filtersquad.com
|
84
|
+
executables: []
|
85
|
+
extensions: []
|
86
|
+
extra_rdoc_files: []
|
87
|
+
files:
|
88
|
+
- .gitignore
|
89
|
+
- .rspec
|
90
|
+
- .rvmrc
|
91
|
+
- Gemfile
|
92
|
+
- Rakefile
|
93
|
+
- lib/unique_generator.rb
|
94
|
+
- lib/unique_generator/version.rb
|
95
|
+
- spec/spec_helper.rb
|
96
|
+
- spec/specific/active_record_spec.rb
|
97
|
+
- spec/specific/mongo_mapper_spec.rb
|
98
|
+
- spec/support/reversible_data_setup.rb
|
99
|
+
- spec/support/shared_unique_specs.rb
|
100
|
+
- spec/unique_generator_spec.rb
|
101
|
+
- unique_generator.gemspec
|
102
|
+
homepage: http://github.com/filtersquad/unique_generator
|
103
|
+
licenses: []
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ! '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 1.8.10
|
123
|
+
signing_key:
|
124
|
+
specification_version: 3
|
125
|
+
summary: Makes generating unique fields in MongoMapper and ActiveRecord easy.
|
126
|
+
test_files:
|
127
|
+
- spec/spec_helper.rb
|
128
|
+
- spec/specific/active_record_spec.rb
|
129
|
+
- spec/specific/mongo_mapper_spec.rb
|
130
|
+
- spec/support/reversible_data_setup.rb
|
131
|
+
- spec/support/shared_unique_specs.rb
|
132
|
+
- spec/unique_generator_spec.rb
|