random_unique_id 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9f9b42d211563950847cf37b80f8c9acc1158463
4
- data.tar.gz: 71c15c22daa64608a593e4b3437d4c417101ad5c
3
+ metadata.gz: e4fd33354ff7f7dc83c2049861a1c1834180a701
4
+ data.tar.gz: e2d3966da120622d465f8ee44a8eafbfa34a07d5
5
5
  SHA512:
6
- metadata.gz: 0c7d1c34b1b6f78412834f3fdcb9415f8b15c3eb8e79d4bd9a5884d6ba06045a4b184eb5bd7837892e96b8d5ed9552c0060726b187202100ee2a277e2e95ab8e
7
- data.tar.gz: 8b52abe0ce84b10d11b9e082e31371b5715140006e5e47dba2861b47a8c92b3c0a8275e9e1160cc6ae620ed0ffd9d300e863a970a849098356b73bdddfbaba5c
6
+ metadata.gz: 3fc7fff7df4603a17669ba6e3a5daf6c8b564f2f1d895497e91081de7b6ef4c2c70668f34b5d554d9ff9b09e9a972d13ca3614111812967bfa5121026ee659dc
7
+ data.tar.gz: 4ef6aece9431d658ad3f034ad709a7a91ca4b3021870bec305c8e8147e3cef0b30fb3f49d16f79136947a0a12d6a40bef066750789b83bdd47d878400571d910
data/Appraisals CHANGED
@@ -1,7 +1,8 @@
1
- # Copyright © 2014, Watu
1
+ # Copyright © 2014, 2015, Watu
2
2
 
3
3
  appraise "rails-3_2" do
4
4
  gem "actionmailer", "~> 3.2.0"
5
+ gem "minitest", "~> 4.7.5"
5
6
  end
6
7
 
7
8
  appraise "rails-4_0" do
@@ -1,5 +1,10 @@
1
1
  Authoritative changelog in README.md.
2
2
 
3
+ ## Version 1.1.0 (Jan 7, 2015)
4
+ - Added global configuration.
5
+ - Added UUID generation.
6
+ - Allow changing the name of the field used for the random id.
7
+
3
8
  ## Version 1.0.1 (Dec 22, 2014)
4
9
  - Added support for Rails 4.2.
5
10
 
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- # Copyright © 2013, 2014, Watu
2
+ # Copyright © 2013, 2014, 2015, Watu
3
3
 
4
4
  source "https://rubygems.org"
5
5
 
@@ -1,4 +1,4 @@
1
- Copyright © 2013, 2014, Watu
1
+ Copyright © 2013, 2014, 2015, Watu
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -69,15 +69,44 @@ records. For example:
69
69
  end
70
70
  end
71
71
 
72
+ ## Configuration
73
+
74
+ There are 2 settings that are configurable for RandomUniqueId:
75
+
76
+ - `min_rid_length:` If you have a large table, the default of 5 characters for an initial length may be a problem, since it may lead to
77
+ several "bounces" until a new unique RID gets generated. The gem scales well with this problem, since it makes
78
+ each subsequent try longer than the one before, but it may still may 3 or 4 DB hits for each record creation.
79
+ In that case, you may want to set it to start with a higher number directly.
80
+
81
+ - `random_generation_method:` If you have a very large table, and having very long IDs is not a problem, you can choose to generate UUIDs instead
82
+ of short-ish Random IDs. This looks worse if you're displaying these IDs in a URL, but it allows to skip the check
83
+ for existence, which in a large table can make a large difference.
84
+ random_generation_method can be either `:short` (the default) or `:uuid`
85
+
86
+ Both of these settings can be specified on a per-model basis, when adding RandomUniqueId to the model:
87
+
88
+ has_random_unique_id(min_rid_length: 10)
89
+ has_random_unique_id(random_generation_method: :uuid)
90
+
91
+ Or globally in an initializer:
92
+
93
+ RandomUniqueId.config(min_rid_length: 10)
94
+
72
95
  ## Users
73
96
 
74
97
  This gem is being used by:
75
98
 
76
99
  - [Watu](https://watuapp.com)
100
+ - [MSTY](https://www.msty.com)
77
101
  - You? please, let us know if you are using this gem.
78
102
 
79
103
  ## Changelog
80
104
 
105
+ ### Version 1.1.0 (Jan 7, 2015)
106
+ - Added global configuration.
107
+ - Added UUID generation.
108
+ - Allow changing the name of the field used for the random id.
109
+
81
110
  ### Version 1.0.1 (Dec 22, 2014)
82
111
  - Added support for Rails 4.2.
83
112
 
@@ -102,12 +131,14 @@ This gem is being used by:
102
131
 
103
132
  1. Fork it
104
133
  1. Create your feature branch (`git checkout -b my-new-feature`)
105
- 1. Code your thing, write tests
106
- 1. Run tests:
134
+ 1. Code your thing
135
+ 1. Write and run tests:
107
136
 
108
137
  bundle install
109
138
  appraisal
110
139
  appraisal rake test
140
+ 1. Write documentation and make sure it looks good: yard server --reload
141
+ 1. Add items to the changelog, both in the README and the CHANGELOG file.
111
142
  1. Commit your changes (`git commit -am "Add some feature"`)
112
143
  1. Push to the branch (`git push origin my-new-feature`)
113
144
  1. Create new Pull Request
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- # Copyright © 2013, 2014, Watu
2
+ # Copyright © 2013, 2014, 2015, Watu
3
3
 
4
4
  require "rubygems"
5
5
  require "bundler/setup"
@@ -3,5 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "actionmailer", "~> 3.2.0"
6
+ gem "minitest", "~> 4.7.5"
6
7
 
7
8
  gemspec :path => "../"
@@ -1,19 +1,19 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- random_unique_id (1.0.1)
4
+ random_unique_id (1.1.0)
5
5
  activerecord (>= 3.2.0)
6
6
  activesupport (>= 3.2.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actionmailer (3.2.19)
12
- actionpack (= 3.2.19)
11
+ actionmailer (3.2.21)
12
+ actionpack (= 3.2.21)
13
13
  mail (~> 2.5.4)
14
- actionpack (3.2.19)
15
- activemodel (= 3.2.19)
16
- activesupport (= 3.2.19)
14
+ actionpack (3.2.21)
15
+ activemodel (= 3.2.21)
16
+ activesupport (= 3.2.21)
17
17
  builder (~> 3.0.0)
18
18
  erubis (~> 2.7.0)
19
19
  journey (~> 1.0.4)
@@ -21,15 +21,15 @@ GEM
21
21
  rack-cache (~> 1.2)
22
22
  rack-test (~> 0.6.1)
23
23
  sprockets (~> 2.2.1)
24
- activemodel (3.2.19)
25
- activesupport (= 3.2.19)
24
+ activemodel (3.2.21)
25
+ activesupport (= 3.2.21)
26
26
  builder (~> 3.0.0)
27
- activerecord (3.2.19)
28
- activemodel (= 3.2.19)
29
- activesupport (= 3.2.19)
27
+ activerecord (3.2.21)
28
+ activemodel (= 3.2.21)
29
+ activesupport (= 3.2.21)
30
30
  arel (~> 3.0.2)
31
31
  tzinfo (~> 0.3.29)
32
- activesupport (3.2.19)
32
+ activesupport (3.2.21)
33
33
  i18n (~> 0.6, >= 0.6.4)
34
34
  multi_json (~> 1.0)
35
35
  ansi (1.4.3)
@@ -39,7 +39,7 @@ GEM
39
39
  thor (>= 0.14.0)
40
40
  arel (3.0.3)
41
41
  builder (3.0.4)
42
- codeclimate-test-reporter (0.4.1)
42
+ codeclimate-test-reporter (0.4.4)
43
43
  simplecov (>= 0.7.1, < 1.0.0)
44
44
  coveralls (0.7.1)
45
45
  multi_json (~> 1.3)
@@ -49,9 +49,9 @@ GEM
49
49
  thor
50
50
  docile (1.1.5)
51
51
  erubis (2.7.0)
52
- hashie (3.3.1)
52
+ hashie (3.3.2)
53
53
  hike (1.2.3)
54
- i18n (0.6.11)
54
+ i18n (0.7.0)
55
55
  journey (1.0.4)
56
56
  json (1.8.1)
57
57
  mail (2.5.4)
@@ -74,7 +74,7 @@ GEM
74
74
  mocha (1.1.0)
75
75
  metaclass (~> 0.0.1)
76
76
  multi_json (1.10.1)
77
- netrc (0.7.7)
77
+ netrc (0.10.2)
78
78
  polyglot (0.3.5)
79
79
  powerbar (1.0.11)
80
80
  ansi (~> 1.4.0)
@@ -86,14 +86,14 @@ GEM
86
86
  rack
87
87
  rack-test (0.6.2)
88
88
  rack (>= 1.0)
89
- railties (3.2.19)
90
- actionpack (= 3.2.19)
91
- activesupport (= 3.2.19)
89
+ railties (3.2.21)
90
+ actionpack (= 3.2.21)
91
+ activesupport (= 3.2.21)
92
92
  rack-ssl (~> 1.3.2)
93
93
  rake (>= 0.8.7)
94
94
  rdoc (~> 3.4)
95
95
  thor (>= 0.14.6, < 2.0)
96
- rake (10.3.2)
96
+ rake (10.4.2)
97
97
  rdoc (3.12.2)
98
98
  json (~> 1.4)
99
99
  rest-client (1.7.2)
@@ -105,26 +105,26 @@ GEM
105
105
  shoulda-context (1.2.1)
106
106
  shoulda-matchers (2.7.0)
107
107
  activesupport (>= 3.0.0)
108
- simplecov (0.9.0)
108
+ simplecov (0.9.1)
109
109
  docile (~> 1.1.0)
110
- multi_json
110
+ multi_json (~> 1.0)
111
111
  simplecov-html (~> 0.8.0)
112
112
  simplecov-html (0.8.0)
113
- sprockets (2.2.2)
113
+ sprockets (2.2.3)
114
114
  hike (~> 1.2)
115
115
  multi_json (~> 1.0)
116
116
  rack (~> 1.0)
117
117
  tilt (~> 1.1, != 1.3.0)
118
- sqlite3 (1.3.9)
118
+ sqlite3 (1.3.10)
119
119
  term-ansicolor (1.3.0)
120
120
  tins (~> 1.0)
121
121
  thor (0.19.1)
122
122
  tilt (1.4.1)
123
- tins (1.3.2)
123
+ tins (1.3.3)
124
124
  treetop (1.4.15)
125
125
  polyglot
126
126
  polyglot (>= 0.3.1)
127
- tzinfo (0.3.41)
127
+ tzinfo (0.3.42)
128
128
 
129
129
  PLATFORMS
130
130
  ruby
@@ -135,7 +135,7 @@ DEPENDENCIES
135
135
  bundler
136
136
  codeclimate-test-reporter
137
137
  coveralls
138
- minitest
138
+ minitest (~> 4.7.5)
139
139
  minitest-rails
140
140
  minitest-reporters
141
141
  mocha
@@ -1,32 +1,32 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- random_unique_id (1.0.1)
4
+ random_unique_id (1.1.0)
5
5
  activerecord (>= 3.2.0)
6
6
  activesupport (>= 3.2.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actionmailer (4.0.9)
12
- actionpack (= 4.0.9)
13
- mail (~> 2.5.4)
14
- actionpack (4.0.9)
15
- activesupport (= 4.0.9)
11
+ actionmailer (4.0.13)
12
+ actionpack (= 4.0.13)
13
+ mail (~> 2.5, >= 2.5.4)
14
+ actionpack (4.0.13)
15
+ activesupport (= 4.0.13)
16
16
  builder (~> 3.1.0)
17
17
  erubis (~> 2.7.0)
18
18
  rack (~> 1.5.2)
19
19
  rack-test (~> 0.6.2)
20
- activemodel (4.0.9)
21
- activesupport (= 4.0.9)
20
+ activemodel (4.0.13)
21
+ activesupport (= 4.0.13)
22
22
  builder (~> 3.1.0)
23
- activerecord (4.0.9)
24
- activemodel (= 4.0.9)
23
+ activerecord (4.0.13)
24
+ activemodel (= 4.0.13)
25
25
  activerecord-deprecated_finders (~> 1.0.2)
26
- activesupport (= 4.0.9)
26
+ activesupport (= 4.0.13)
27
27
  arel (~> 4.0.0)
28
28
  activerecord-deprecated_finders (1.0.3)
29
- activesupport (4.0.9)
29
+ activesupport (4.0.13)
30
30
  i18n (~> 0.6, >= 0.6.9)
31
31
  minitest (~> 4.2)
32
32
  multi_json (~> 1.3)
@@ -39,7 +39,7 @@ GEM
39
39
  thor (>= 0.14.0)
40
40
  arel (4.0.2)
41
41
  builder (3.1.4)
42
- codeclimate-test-reporter (0.4.1)
42
+ codeclimate-test-reporter (0.4.4)
43
43
  simplecov (>= 0.7.1, < 1.0.0)
44
44
  coveralls (0.7.1)
45
45
  multi_json (~> 1.3)
@@ -49,13 +49,12 @@ GEM
49
49
  thor
50
50
  docile (1.1.5)
51
51
  erubis (2.7.0)
52
- hashie (3.3.1)
53
- i18n (0.6.11)
54
- mail (2.5.4)
55
- mime-types (~> 1.16)
56
- treetop (~> 1.4.8)
52
+ hashie (3.3.2)
53
+ i18n (0.7.0)
54
+ mail (2.6.3)
55
+ mime-types (>= 1.16, < 3)
57
56
  metaclass (0.0.4)
58
- mime-types (1.25.1)
57
+ mime-types (2.4.3)
59
58
  minitest (4.7.5)
60
59
  minitest-rails (1.0.1)
61
60
  minitest (~> 4.7)
@@ -71,20 +70,19 @@ GEM
71
70
  mocha (1.1.0)
72
71
  metaclass (~> 0.0.1)
73
72
  multi_json (1.10.1)
74
- netrc (0.7.7)
75
- polyglot (0.3.5)
73
+ netrc (0.10.2)
76
74
  powerbar (1.0.11)
77
75
  ansi (~> 1.4.0)
78
76
  hashie (>= 1.1.0)
79
77
  rack (1.5.2)
80
78
  rack-test (0.6.2)
81
79
  rack (>= 1.0)
82
- railties (4.0.9)
83
- actionpack (= 4.0.9)
84
- activesupport (= 4.0.9)
80
+ railties (4.0.13)
81
+ actionpack (= 4.0.13)
82
+ activesupport (= 4.0.13)
85
83
  rake (>= 0.8.7)
86
84
  thor (>= 0.18.1, < 2.0)
87
- rake (10.3.2)
85
+ rake (10.4.2)
88
86
  rest-client (1.7.2)
89
87
  mime-types (>= 1.16, < 3.0)
90
88
  netrc (~> 0.7)
@@ -94,21 +92,18 @@ GEM
94
92
  shoulda-context (1.2.1)
95
93
  shoulda-matchers (2.7.0)
96
94
  activesupport (>= 3.0.0)
97
- simplecov (0.9.0)
95
+ simplecov (0.9.1)
98
96
  docile (~> 1.1.0)
99
- multi_json
97
+ multi_json (~> 1.0)
100
98
  simplecov-html (~> 0.8.0)
101
99
  simplecov-html (0.8.0)
102
- sqlite3 (1.3.9)
100
+ sqlite3 (1.3.10)
103
101
  term-ansicolor (1.3.0)
104
102
  tins (~> 1.0)
105
103
  thor (0.19.1)
106
104
  thread_safe (0.3.4)
107
- tins (1.3.2)
108
- treetop (1.4.15)
109
- polyglot
110
- polyglot (>= 0.3.1)
111
- tzinfo (0.3.41)
105
+ tins (1.3.3)
106
+ tzinfo (0.3.42)
112
107
 
113
108
  PLATFORMS
114
109
  ruby
@@ -1,34 +1,34 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- random_unique_id (1.0.1)
4
+ random_unique_id (1.1.0)
5
5
  activerecord (>= 3.2.0)
6
6
  activesupport (>= 3.2.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actionmailer (4.1.5)
12
- actionpack (= 4.1.5)
13
- actionview (= 4.1.5)
14
- mail (~> 2.5.4)
15
- actionpack (4.1.5)
16
- actionview (= 4.1.5)
17
- activesupport (= 4.1.5)
11
+ actionmailer (4.1.9)
12
+ actionpack (= 4.1.9)
13
+ actionview (= 4.1.9)
14
+ mail (~> 2.5, >= 2.5.4)
15
+ actionpack (4.1.9)
16
+ actionview (= 4.1.9)
17
+ activesupport (= 4.1.9)
18
18
  rack (~> 1.5.2)
19
19
  rack-test (~> 0.6.2)
20
- actionview (4.1.5)
21
- activesupport (= 4.1.5)
20
+ actionview (4.1.9)
21
+ activesupport (= 4.1.9)
22
22
  builder (~> 3.1)
23
23
  erubis (~> 2.7.0)
24
- activemodel (4.1.5)
25
- activesupport (= 4.1.5)
24
+ activemodel (4.1.9)
25
+ activesupport (= 4.1.9)
26
26
  builder (~> 3.1)
27
- activerecord (4.1.5)
28
- activemodel (= 4.1.5)
29
- activesupport (= 4.1.5)
27
+ activerecord (4.1.9)
28
+ activemodel (= 4.1.9)
29
+ activesupport (= 4.1.9)
30
30
  arel (~> 5.0.0)
31
- activesupport (4.1.5)
31
+ activesupport (4.1.9)
32
32
  i18n (~> 0.6, >= 0.6.9)
33
33
  json (~> 1.7, >= 1.7.7)
34
34
  minitest (~> 5.1)
@@ -41,7 +41,7 @@ GEM
41
41
  thor (>= 0.14.0)
42
42
  arel (5.0.1.20140414130214)
43
43
  builder (3.2.2)
44
- codeclimate-test-reporter (0.4.1)
44
+ codeclimate-test-reporter (0.4.4)
45
45
  simplecov (>= 0.7.1, < 1.0.0)
46
46
  coveralls (0.7.1)
47
47
  multi_json (~> 1.3)
@@ -51,18 +51,17 @@ GEM
51
51
  thor
52
52
  docile (1.1.5)
53
53
  erubis (2.7.0)
54
- i18n (0.6.11)
54
+ i18n (0.7.0)
55
55
  json (1.8.1)
56
- mail (2.5.4)
57
- mime-types (~> 1.16)
58
- treetop (~> 1.4.8)
56
+ mail (2.6.3)
57
+ mime-types (>= 1.16, < 3)
59
58
  metaclass (0.0.4)
60
- mime-types (1.25.1)
61
- minitest (5.4.1)
62
- minitest-rails (2.1.0)
59
+ mime-types (2.4.3)
60
+ minitest (5.5.0)
61
+ minitest-rails (2.1.1)
63
62
  minitest (~> 5.4)
64
63
  railties (~> 4.1)
65
- minitest-reporters (1.0.5)
64
+ minitest-reporters (1.0.8)
66
65
  ansi
67
66
  builder
68
67
  minitest (>= 5.0)
@@ -70,41 +69,37 @@ GEM
70
69
  mocha (1.1.0)
71
70
  metaclass (~> 0.0.1)
72
71
  multi_json (1.10.1)
73
- netrc (0.7.7)
74
- polyglot (0.3.5)
72
+ netrc (0.10.2)
75
73
  rack (1.5.2)
76
74
  rack-test (0.6.2)
77
75
  rack (>= 1.0)
78
- railties (4.1.5)
79
- actionpack (= 4.1.5)
80
- activesupport (= 4.1.5)
76
+ railties (4.1.9)
77
+ actionpack (= 4.1.9)
78
+ activesupport (= 4.1.9)
81
79
  rake (>= 0.8.7)
82
80
  thor (>= 0.18.1, < 2.0)
83
- rake (10.3.2)
81
+ rake (10.4.2)
84
82
  rest-client (1.7.2)
85
83
  mime-types (>= 1.16, < 3.0)
86
84
  netrc (~> 0.7)
87
- ruby-progressbar (1.5.1)
85
+ ruby-progressbar (1.7.1)
88
86
  shoulda (3.5.0)
89
87
  shoulda-context (~> 1.0, >= 1.0.1)
90
88
  shoulda-matchers (>= 1.4.1, < 3.0)
91
89
  shoulda-context (1.2.1)
92
90
  shoulda-matchers (2.7.0)
93
91
  activesupport (>= 3.0.0)
94
- simplecov (0.9.0)
92
+ simplecov (0.9.1)
95
93
  docile (~> 1.1.0)
96
- multi_json
94
+ multi_json (~> 1.0)
97
95
  simplecov-html (~> 0.8.0)
98
96
  simplecov-html (0.8.0)
99
- sqlite3 (1.3.9)
97
+ sqlite3 (1.3.10)
100
98
  term-ansicolor (1.3.0)
101
99
  tins (~> 1.0)
102
100
  thor (0.19.1)
103
101
  thread_safe (0.3.4)
104
- tins (1.3.2)
105
- treetop (1.4.15)
106
- polyglot
107
- polyglot (>= 0.3.1)
102
+ tins (1.3.3)
108
103
  tzinfo (1.2.2)
109
104
  thread_safe (~> 0.1)
110
105
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- random_unique_id (1.0.1)
4
+ random_unique_id (1.1.0)
5
5
  activerecord (>= 3.2.0)
6
6
  activesupport (>= 3.2.0)
7
7
 
@@ -50,7 +50,7 @@ GEM
50
50
  thor (>= 0.14.0)
51
51
  arel (6.0.0)
52
52
  builder (3.2.2)
53
- codeclimate-test-reporter (0.4.3)
53
+ codeclimate-test-reporter (0.4.4)
54
54
  simplecov (>= 0.7.1, < 1.0.0)
55
55
  coveralls (0.7.1)
56
56
  multi_json (~> 1.3)
@@ -70,7 +70,7 @@ GEM
70
70
  mime-types (>= 1.16, < 3)
71
71
  metaclass (0.0.4)
72
72
  mime-types (2.4.3)
73
- mini_portile (0.6.1)
73
+ mini_portile (0.6.2)
74
74
  minitest (5.5.0)
75
75
  minitest-rails (2.1.1)
76
76
  minitest (~> 5.4)
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- # Copyright © 2011, 2012, 2013, 2014, Watu
2
+ # Copyright © 2011, 2012, 2013, 2014, 2015, Watu
3
3
 
4
4
  require "random_unique_id/version"
5
5
  require "securerandom"
@@ -9,6 +9,27 @@ require "active_record"
9
9
  module RandomUniqueId
10
10
  extend ActiveSupport::Concern
11
11
 
12
+ @@config = nil
13
+
14
+ # The global configuration for RandomUniqueID.
15
+ # Set it in initializers
16
+ #
17
+ # RandomUniqueId.config(field: :rid,
18
+ # random_generation_method: :short,
19
+ # min_rid_length: 5)
20
+ #
21
+ # @param [Hash] options
22
+ # @option options [Symbol] field the name of the field where the random unique id is stored.
23
+ # @option options [Symbol] random_generation_method the method to generate random IDs, `:short` or `:uuid`.
24
+ # `:short` will generate a short-ish random ID, and check that it is unique
25
+ # `:uuid` will generate a UUID, and skip the check. This is better for performance, and bad for readability of IDs
26
+ # @option options [FixNum] min_rid_length the minimum length RandomUniqueID will generate. Defaults to 5
27
+ # @return [Hash] the configuration.
28
+ def self.config(options={})
29
+ @@config ||= {field: :rid, random_generation_method: :short, min_rid_length: 5}
30
+ @@config = @@config.merge(options)
31
+ end
32
+
12
33
  # Collection of methods that will end as class methods of ActiveRecord::Base.
13
34
  #
14
35
  # @see ActiveSupport::Concern
@@ -25,10 +46,14 @@ module RandomUniqueId
25
46
  # has_random_unique_id
26
47
  # # ... other stuff
27
48
  # end
28
- def has_random_unique_id
29
- validates :rid, presence: true, uniqueness: true
30
- before_validation :generate_random_unique_id, if: Proc.new { |r| r.rid.blank? }
31
- define_method(:to_param) { rid }
49
+ #
50
+ # @param options [Hash] generation options, same as RandomUniqueID.config, in case the generation method or minimum
51
+ # length needs to be overridden for one specific model
52
+ def has_random_unique_id(options={})
53
+ options = RandomUniqueId.config.merge(options)
54
+ before_validation :populate_rid_field, if: Proc.new { |r| r.send(options[:field]).blank? }
55
+ add_rid_related_validations(options)
56
+ add_rid_related_methods(options)
32
57
  end
33
58
 
34
59
  # Augment the ActiveRecord belongs_to to also define rid accessors. For example: if you blog post belongs_to an
@@ -70,9 +95,9 @@ module RandomUniqueId
70
95
  def populate_random_unique_ids
71
96
  find_each do |record|
72
97
  rid_just_populated = false
73
- if record.rid.blank?
74
- record.generate_random_unique_id
75
- record.update_column(:rid, record.rid)
98
+ if record.send(record.random_unique_id_options[:field]).blank?
99
+ record.populate_rid_field
100
+ record.update_column(record.random_unique_id_options[:field], record.send(record.random_unique_id_options[:field]))
76
101
  rid_just_populated = true
77
102
  end
78
103
  yield(record, rid_just_populated) if block_given?
@@ -81,6 +106,20 @@ module RandomUniqueId
81
106
 
82
107
  private
83
108
 
109
+ # Add the rid related methods to the model.
110
+ # @param options [Hash] same as in RandomUniqueID.config
111
+ def add_rid_related_methods(options)
112
+ define_method(:to_param) { send(options[:field]) }
113
+ define_method(:random_unique_id_options) { options } # I don't think this is the best way to store this, but I didn't find a better one.
114
+ end
115
+
116
+ # Add the rid related validations to the model.
117
+ # @param options [Hash] same as in RandomUniqueID.config
118
+ def add_rid_related_validations(options)
119
+ validates(options[:field], presence: true)
120
+ validates(options[:field], uniqueness: true) if options[:random_generation_method] != :uuid # If we're generating UUIDs, don't check for uniqueness
121
+ end
122
+
84
123
  # Defines the setter and getter for the RID of a relationship.
85
124
  #
86
125
  # @param related_class [Class] class in which the RID methods are going to be defined.
@@ -88,7 +127,7 @@ module RandomUniqueId
88
127
  # @see RandomUniqueId::ClassMethods.belongs_to
89
128
  def define_rid_accessors(related_class, relationship_name)
90
129
  define_method("#{relationship_name}_rid") do
91
- self.send(relationship_name).try(:rid)
130
+ self.send(relationship_name).try(random_unique_id_options[:field])
92
131
  end
93
132
 
94
133
  define_method("#{relationship_name}_rid=") do |rid|
@@ -101,43 +140,70 @@ module RandomUniqueId
101
140
 
102
141
  # Generate and store the random unique id for the object.
103
142
  #
104
- # @param n [Integer] how long should the random string be.
143
+ # @param length [Integer] how long should the random string be. Only applicable for `:short` type.
105
144
  # @param field [String] name of the field that contains the rid.
106
145
  # @return [String] the random string.
107
146
  # @see RandomUniqueId::ClassMethods#has_random_unique_id
108
147
  # @see RandomUniqueId.generate_random_id
109
- def generate_random_unique_id(n=5, field="rid")
110
- # Find the topmost class before ActiveRecord::Base so that when we do queries, we don't end up with type=Whatever in the where clause.
111
- klass = self.class
112
- self.class.ancestors.each do |k|
113
- if k == ActiveRecord::Base
114
- break # we reached the bottom of this barrel
115
- end
116
- if k.is_a? Class
117
- klass = k
118
- end
148
+ def populate_rid_field(length=random_unique_id_options[:min_rid_length], field=random_unique_id_options[:field])
149
+ case random_unique_id_options[:random_generation_method]
150
+ when :short
151
+ self.send("#{field}=", generate_short_random_unique_id(length, field))
152
+ when :uuid
153
+ self.send("#{field}=", RandomUniqueId.generate_uuid)
154
+ else
155
+ raise "Invalid random generation method: #{self.random_unique_id_options[:random_generation_method]}"
119
156
  end
157
+ end
120
158
 
159
+ # Generate random ids, increasing their size, until one is found that is not used for another record in the database.
160
+ # @param length [Integer] how long should the random string be.
161
+ # @param field [String] name of the field that contains the rid.
162
+ def generate_short_random_unique_id(length, field)
163
+ potential_unique_random_id = nil
121
164
  begin
122
- self.send("#{field}=", RandomUniqueId.generate_random_id(n))
123
- n += 1
124
- end while klass.unscoped.where(field => self.send(field)).exists?
165
+ potential_unique_random_id = RandomUniqueId.generate_short_random_id(length)
166
+ length += 1
167
+ end while topmost_model_class.unscoped.where(field => potential_unique_random_id).exists?
168
+ potential_unique_random_id
169
+ end
170
+
171
+ # Find the topmost class before ActiveRecord::Base so that when we do queries, we don't end up with type=Whatever in
172
+ # the where clause.
173
+ # @return [Class] the class object
174
+ def topmost_model_class
175
+ @topmost_model_class ||= begin
176
+ klass = self.class
177
+ self.class.ancestors.select { |k| k.is_a? Class }.each do |k|
178
+ if k == ActiveRecord::Base
179
+ return klass
180
+ end
181
+ klass = k
182
+ end
183
+ end
125
184
  end
126
185
 
127
186
  # By a cunning use of SecureRandom.urlsafe_base64, quickly generate an alphanumeric random string.
128
187
  #
129
- # @param n [Integer] how long should the random string be.
188
+ # @param length [Integer] how long should the random string be.
130
189
  # @return [String] the random string.
131
- # @see RandomUniqueId#generate_random_unique_id
132
- def self.generate_random_id(n=10)
190
+ # @see RandomUniqueId#populate_rid_field
191
+ def self.generate_short_random_id(length=10)
133
192
  # IMPORTANT: don't ever generate dashes or underscores in the RIDs as they are likely to end up in the UI in Rails
134
193
  # and they'll be converted to something else by jquery ujs or something like that.
135
194
  generated_rid = ""
136
- while generated_rid.length < n
137
- generated_rid = (generated_rid + SecureRandom.urlsafe_base64(n * 3).downcase.gsub(/[^a-z0-9]/, ""))[0..(n-1)]
195
+ while generated_rid.length < length
196
+ generated_rid = (generated_rid + SecureRandom.urlsafe_base64(length * 3).downcase.gsub(/[^a-z0-9]/, ""))[0..(length-1)]
138
197
  end
139
198
  return generated_rid
140
199
  end
200
+
201
+ # Generate a UUID. Just a wrapper around SecureRandom.uuid
202
+ # @return [String] the new UUID.
203
+ # @see RandomUniqueId#populate_rid_field
204
+ def self.generate_uuid
205
+ SecureRandom.uuid
206
+ end
141
207
  end
142
208
 
143
209
  ActiveRecord::Base.send(:include, RandomUniqueId)
@@ -1,4 +1,4 @@
1
- # Copyright © 2014, Watu
1
+ # Copyright © 2014, 2015, Watu
2
2
 
3
3
  # Some utilities that might be useful if you are using RandomUniqueId. This file needs to be explicitely included:
4
4
  #
@@ -35,4 +35,4 @@ module RandomUniqueId::Util
35
35
  raise "Don't know how to set initial ids for #{sql_connection.adapter_name}. Would you like to contribute? https://github.com/watu/random_unique_id"
36
36
  end
37
37
  end
38
- end
38
+ end
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
- # Copyright © 2013, 2014, Watu
2
+ # Copyright © 2013, 2014, 2015, Watu
3
3
 
4
4
  module RandomUniqueId
5
- VERSION = "1.0.1"
5
+ VERSION = "1.1.0"
6
6
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- # Copyright © 2013, 2014, Watu
2
+ # Copyright © 2013, 2014, 2015, Watu
3
3
 
4
4
  lib = File.expand_path("../lib", __FILE__)
5
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -8,7 +8,7 @@ require "random_unique_id/version"
8
8
  Gem::Specification.new do |spec|
9
9
  spec.name = "random_unique_id"
10
10
  spec.version = RandomUniqueId::VERSION
11
- spec.authors = ["J. Pablo Fernández"]
11
+ spec.authors = ["J. Pablo Fernández", "Daniel Magliola"]
12
12
  spec.email = ["pupeno@watuapp.com"]
13
13
  spec.homepage = "https://github.com/watu/random_unique_id"
14
14
  spec.summary = %q{Generate random but unique ids for your active record records.}
@@ -1,4 +1,4 @@
1
- # Copyright © 2014, Watu
1
+ # Copyright © 2014, 2015, Watu
2
2
 
3
3
  require_relative "../test_helper"
4
4
 
@@ -25,4 +25,4 @@ class RandomUniqueId::UtilTest < MiniTest::Unit::TestCase
25
25
  ActiveRecord::Base.expects(:connection).returns(sql_connection)
26
26
  RandomUniqueId::Util.set_initial_ids
27
27
  end
28
- end
28
+ end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- # Copyright © 2011, 2012, 2013, 2014, Watu
2
+ # Copyright © 2011, 2012, 2013, 2014, 2015, Watu
3
3
 
4
4
  require_relative "test_helper"
5
5
 
@@ -18,6 +18,20 @@ ActiveRecord::Schema.define(version: 0) do
18
18
  t.integer :blog_id
19
19
  end
20
20
  add_index :posts, :rid, unique: true
21
+
22
+ create_table :comments do |t|
23
+ t.string :random_id
24
+ t.string :text
25
+ t.integer :post_id
26
+ end
27
+ add_index :comments, :random_id, unique: true
28
+
29
+ create_table :post_views do |t|
30
+ t.string :rid
31
+ t.string :ip_address
32
+ t.integer :post_id
33
+ end
34
+ add_index :post_views, :rid # NOT unique, for performance, it'll store UUIDs so we don't need to check
21
35
  end
22
36
 
23
37
  class Blog < ActiveRecord::Base
@@ -25,6 +39,28 @@ class Blog < ActiveRecord::Base
25
39
  has_random_unique_id
26
40
  end
27
41
 
42
+ class BlogWithInvalidGenerationMethod < ActiveRecord::Base
43
+ self.table_name = "blogs"
44
+ has_random_unique_id(random_generation_method: :invalid) # Used to test the exception when you specify the wrong method
45
+ end
46
+
47
+ original_config = RandomUniqueId.config
48
+ RandomUniqueId.config(random_generation_method: :uuid)
49
+
50
+ class BlogWithUuid < ActiveRecord::Base
51
+ self.table_name = "blogs"
52
+ has_random_unique_id
53
+ end
54
+
55
+ RandomUniqueId.config(random_generation_method: :short, min_rid_length: 12)
56
+
57
+ class BlogWithLongRid < ActiveRecord::Base
58
+ self.table_name = "blogs"
59
+ has_random_unique_id
60
+ end
61
+
62
+ RandomUniqueId.config(original_config)
63
+
28
64
  class Post < ActiveRecord::Base
29
65
  belongs_to :blog
30
66
  has_random_unique_id
@@ -36,6 +72,15 @@ end
36
72
  class ImagePost < Post
37
73
  end
38
74
 
75
+ class Comment < ActiveRecord::Base
76
+ belongs_to :post
77
+ has_random_unique_id(field: :random_id, min_rid_length: 10) # Comments have longer RIDs, since it's a big table and we were getting lots of collissions
78
+ end
79
+
80
+ class PostView < ActiveRecord::Base
81
+ belongs_to :post
82
+ has_random_unique_id(random_generation_method: :uuid) # Post Views have UUIDs instead of RIDs, since the table is ginormous, so it can't check for existence every time.
83
+ end
39
84
 
40
85
  class RandomUniqueIdTest < MiniTest::Unit::TestCase
41
86
  context "With a record with random id" do
@@ -51,9 +96,9 @@ class RandomUniqueIdTest < MiniTest::Unit::TestCase
51
96
 
52
97
  should "resolve random id collision" do
53
98
  # Mock RandomUniqueId to return a collision on the first call, and hopefully a non collision on the second, expecting n to grow by one.
54
- RandomUniqueId.expects(:generate_random_id).with(5).returns(@text_post.rid)
99
+ RandomUniqueId.expects(:generate_short_random_id).with(5).returns(@text_post.rid)
55
100
  new_rid = @text_post.rid + "i"
56
- RandomUniqueId.expects(:generate_random_id).with(6).returns(new_rid)
101
+ RandomUniqueId.expects(:generate_short_random_id).with(6).returns(new_rid)
57
102
 
58
103
  new_record = TextPost.create! # No exception should be raised.
59
104
  assert_equal new_rid, new_record.rid
@@ -61,9 +106,9 @@ class RandomUniqueIdTest < MiniTest::Unit::TestCase
61
106
 
62
107
  should "resolve random id collision in different classes of the same table (due to STI)" do
63
108
  # Mock RandomUniqueId to return a collision on the first call, and hopefully a non collision on the second, expecting n to grow by one.
64
- RandomUniqueId.expects(:generate_random_id).with(5).returns(@text_post.rid)
109
+ RandomUniqueId.expects(:generate_short_random_id).with(5).returns(@text_post.rid)
65
110
  new_rid = @text_post.rid + "i"
66
- RandomUniqueId.expects(:generate_random_id).with(6).returns(new_rid)
111
+ RandomUniqueId.expects(:generate_short_random_id).with(6).returns(new_rid)
67
112
 
68
113
  new_record = ImagePost.create! # No exception should be raised.
69
114
  assert_equal new_rid, new_record.rid
@@ -80,18 +125,76 @@ class RandomUniqueIdTest < MiniTest::Unit::TestCase
80
125
  end
81
126
 
82
127
  should "populate a table with rids" do
83
- # Create a bunch of blogs without rid by manually inserting them into the talbe.
128
+ # Create a bunch of blogs without rid by manually inserting them into the table.
84
129
  rid_less_records = 10
85
130
  5.times { Blog.create! }
86
131
  existing_rids = Blog.all.map(&:rid).compact
87
132
  rid_less_records.times { Blog.connection.execute("INSERT INTO blogs (name) VALUES ('Blag')") }
88
- assert_equal rid_less_records, Blog.where(:rid => nil).count # Just to be sure this test is being effective.
133
+ assert_equal rid_less_records, Blog.where(rid: nil).count # Just to be sure this test is being effective.
89
134
 
90
135
  rids_populated = 0
91
136
  Blog.populate_random_unique_ids { |_, rid_just_populated| rids_populated += 1 if rid_just_populated }
92
137
  assert_equal rid_less_records, rids_populated
93
- assert_equal 0, Blog.where(:rid => nil).count
94
- assert_equal existing_rids.count, Blog.where(:rid => existing_rids).count # Make sure the existing rids where not touched.
138
+ assert_equal 0, Blog.where(rid: nil).count
139
+ assert_equal existing_rids.count, Blog.where(rid: existing_rids).count # Make sure the existing rids where not touched.
140
+ end
141
+
142
+ should "populate a table with rids with custom field name" do
143
+ # Create a bunch of comments without rid by manually inserting them into the table
144
+ rid_less_records = 10
145
+ blog = Blog.create!
146
+ post = Post.create!(blog: blog)
147
+ 5.times { Comment.create!(post: post) }
148
+ existing_rids = Comment.all.map(&:random_id).compact
149
+ rid_less_records.times { Comment.connection.execute("INSERT INTO comments (post_id) VALUES (#{post.id})") }
150
+ assert_equal rid_less_records, Comment.where(random_id: nil).count # Just to be sure this test is being effective.
151
+
152
+ rids_populated = 0
153
+ Comment.populate_random_unique_ids { |_, rid_just_populated| rids_populated += 1 if rid_just_populated }
154
+ assert_equal rid_less_records, rids_populated
155
+ assert_equal 0, Comment.where(random_id: nil).count
156
+ assert_equal existing_rids.count, Comment.where(random_id: existing_rids).count # Make sure the existing rids where not touched.
157
+ end
158
+ end
159
+
160
+ context "With an invalid generation method" do
161
+ should "Raise exception on RID geneartion" do
162
+ assert_raises RuntimeError do
163
+ BlogWithInvalidGenerationMethod.create!
164
+ end
165
+ end
166
+ end
167
+
168
+ # Tests for configuration options, both global and model overrides
169
+ context "With a global configuration for UUIDs" do
170
+ should "generate UUID" do
171
+ blog = BlogWithUuid.create!
172
+ assert_match /(\w{8}(-\w{4}){3}-\w{12}?)/, blog.rid
173
+ end
174
+ end
175
+
176
+ context "With a global configuration for long RIDs" do
177
+ should "generate long RID" do
178
+ blog = BlogWithLongRid.create!
179
+ assert blog.rid.length >= 12, "RID must be at least 12 chars long"
180
+ assert !(blog.rid =~ /(\w{8}(-\w{4}){3}-\w{12}?)/), "RID must not be a UUID"
181
+ end
182
+ end
183
+
184
+ context "With models that have overrides for RID configuration" do
185
+ should "Generate short RID for normal model" do
186
+ blog = Blog.create!
187
+ assert_equal 5, blog.rid.length
188
+ end
189
+
190
+ should "Generate long RID for model that requested min_rid_length" do
191
+ comment = Comment.create!
192
+ assert_equal 10, comment.random_id.length
193
+ end
194
+
195
+ should "Generate UUID for model that requested UUID random_generation_method" do
196
+ postview = PostView.create!
197
+ assert_match /(\w{8}(-\w{4}){3}-\w{12}?)/, postview.rid
95
198
  end
96
199
  end
97
200
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- # Copyright © 2013, 2014, Watu
2
+ # Copyright © 2013, 2014, 2015, Watu
3
3
 
4
4
  require "rubygems"
5
5
 
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: random_unique_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - J. Pablo Fernández
8
+ - Daniel Magliola
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-12-22 00:00:00.000000000 Z
12
+ date: 2015-01-07 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activesupport