random_unique_id 1.0.1 → 1.1.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.
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