random_unique_id 0.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 +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +7 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +22 -0
- data/README.md +48 -0
- data/Rakefile +12 -0
- data/gemfiles/rails_3_2.Gemfile +16 -0
- data/gemfiles/rails_4_0.Gemfile +16 -0
- data/lib/random_unique_id/version.rb +6 -0
- data/lib/random_unique_id.rb +76 -0
- data/random_unique_id.gemspec +25 -0
- data/test/random_unique_id_test.rb +81 -0
- data/test/test_helper.rb +36 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0a7b92c76f522b3336630120ac9d9b882eaef76c
|
4
|
+
data.tar.gz: b5664b1d2c1bbb5942c5a94fbc89e66b8eb7c61d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f7ccd53a8efdbc946946a1be8180bae4b5b62c1325591a129d5b1d1a9d636d2e8e2fffc5044230edb540cd05bd7b61deae7b5fc047663b9346cc42da3cc42647
|
7
|
+
data.tar.gz: 5115455385496f828995823603bc4a5caa92d14e7688c65a8e28173579d1805e3836aab7d77936453b03eea96ad02377cb53e41f898493906202e2043e10de8d
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Copyright © 2013, Watu
|
3
|
+
|
4
|
+
source "https://rubygems.org"
|
5
|
+
|
6
|
+
gem "bundler", "~> 1.3"
|
7
|
+
gem "coveralls", require: false
|
8
|
+
gem "minitest"
|
9
|
+
gem "minitest-reporters"
|
10
|
+
gem "mocha"
|
11
|
+
gem "rake"
|
12
|
+
gem "simplecov"
|
13
|
+
gem "shoulda"
|
14
|
+
gem "sqlite3"
|
15
|
+
gem "activesupport", "~> 4.0.0"
|
16
|
+
gem "activerecord", "~> 4.0.0"
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright © 2013, Watu
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Random Unique ID
|
2
|
+
|
3
|
+
[](https://travis-ci.org/watu/random_unique_id)
|
4
|
+
[](https://coveralls.io/r/watu/random_unique_id?branch=master)
|
5
|
+
|
6
|
+
This gem will generate a random unique id for your active record records that you can use instead of their actual ID for
|
7
|
+
all external interactions with users. The goal is for you to be able to hide how many records you have, for business
|
8
|
+
purposes, but also to make IDs non-predictable.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem "random_unique_id"
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install random_unique_id
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
The usage is very simple. For each record where you want to have a random id generated, add the following line to the
|
27
|
+
class:
|
28
|
+
|
29
|
+
has_random_unique_id
|
30
|
+
|
31
|
+
For example:
|
32
|
+
|
33
|
+
class Post < ActiveRecord::Base
|
34
|
+
has_random_unique_id
|
35
|
+
end
|
36
|
+
|
37
|
+
You need to also add a column, called `rid` of type string/varchar. It is recommended that you also add an index on that
|
38
|
+
column.
|
39
|
+
|
40
|
+
The method to_param will be overridden to return the rid instead of the id.
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
1. Fork it
|
45
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
46
|
+
3. Commit your changes (`git commit -am "Add some feature"`)
|
47
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
48
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Copyright © 2013, Watu
|
3
|
+
|
4
|
+
source "https://rubygems.org"
|
5
|
+
|
6
|
+
gem "bundler", "~> 1.3"
|
7
|
+
gem "coveralls", require: false
|
8
|
+
gem "minitest", "~> 2.5.1"
|
9
|
+
gem "minitest-reporters"
|
10
|
+
gem "mocha"
|
11
|
+
gem "rake"
|
12
|
+
gem "simplecov"
|
13
|
+
gem "shoulda"
|
14
|
+
gem "sqlite3"
|
15
|
+
gem "activesupport", "~> 3.2.0"
|
16
|
+
gem "activerecord", "~> 3.2.0"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Copyright © 2013, Watu
|
3
|
+
|
4
|
+
source "https://rubygems.org"
|
5
|
+
|
6
|
+
gem "bundler", "~> 1.3"
|
7
|
+
gem "coveralls", require: false
|
8
|
+
gem "minitest"
|
9
|
+
gem "minitest-reporters"
|
10
|
+
gem "mocha"
|
11
|
+
gem "rake"
|
12
|
+
gem "simplecov"
|
13
|
+
gem "shoulda"
|
14
|
+
gem "sqlite3"
|
15
|
+
gem "activesupport", "~> 4.0.0"
|
16
|
+
gem "activerecord", "~> 4.0.0"
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Copyright © 2011, 2012, 2013, Watu
|
3
|
+
|
4
|
+
require "random_unique_id/version"
|
5
|
+
require "securerandom"
|
6
|
+
require "active_support"
|
7
|
+
require "active_record"
|
8
|
+
|
9
|
+
module RandomUniqueId
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def has_random_unique_id
|
14
|
+
validates :rid, presence: true, uniqueness: true
|
15
|
+
before_validation :generate_random_unique_id, if: Proc.new { |r| r.rid.blank? }
|
16
|
+
define_method(:to_param) { rid }
|
17
|
+
end
|
18
|
+
|
19
|
+
def belongs_to(*attrs)
|
20
|
+
define_rid_method = attrs[1].try(:delete, :rid)
|
21
|
+
super.tap do
|
22
|
+
if define_rid_method != false
|
23
|
+
rel_name = attrs[0]
|
24
|
+
rel = reflections[rel_name]
|
25
|
+
|
26
|
+
return if rel.options[:polymorphic] # If we don't know the class, we cannot find the record by rid.
|
27
|
+
|
28
|
+
class_name = rel.options[:class_name] || rel_name.to_s.classify
|
29
|
+
klass = class_name.constantize
|
30
|
+
|
31
|
+
if klass.attribute_names.include? "rid"
|
32
|
+
define_method("#{rel_name}_rid") do
|
33
|
+
self.send(rel_name).try(:rid)
|
34
|
+
end
|
35
|
+
|
36
|
+
define_method("#{rel_name}_rid=") do |rid|
|
37
|
+
record = klass.find_by_rid(rid)
|
38
|
+
self.send("#{rel_name}=", record)
|
39
|
+
record
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate_random_unique_id(n=5, field="rid")
|
48
|
+
# 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.
|
49
|
+
klass = self.class
|
50
|
+
self.class.ancestors.each do |k|
|
51
|
+
if k == ActiveRecord::Base
|
52
|
+
break # we reached the bottom of this barrel
|
53
|
+
end
|
54
|
+
if k.is_a? Class
|
55
|
+
klass = k
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
begin
|
60
|
+
self.send("#{field}=", RandomUniqueId.generate_random_id(n))
|
61
|
+
n += 1
|
62
|
+
end while klass.unscoped.where(field => self.send(field)).exists?
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.generate_random_id(n=10)
|
66
|
+
# IMPORTANT: don't ever generate dashes or underscores in the RIDs as they are likely to end up in the UI in Rails
|
67
|
+
# and they'll be converted to something else by jquery ujs or something like that.
|
68
|
+
generated_rid = ""
|
69
|
+
while generated_rid.length < n
|
70
|
+
generated_rid = (generated_rid + SecureRandom.urlsafe_base64(n * 3).downcase.gsub(/[^a-z0-9]/, ""))[0..(n-1)]
|
71
|
+
end
|
72
|
+
return generated_rid
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
ActiveRecord::Base.send(:include, RandomUniqueId)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Copyright © 2013, Watu
|
3
|
+
|
4
|
+
lib = File.expand_path("../lib", __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
require "random_unique_id/version"
|
7
|
+
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = "random_unique_id"
|
10
|
+
spec.version = RandomUniqueId::VERSION
|
11
|
+
spec.authors = ["J. Pablo Fernández"]
|
12
|
+
spec.email = ["pupeno@watuapp.com"]
|
13
|
+
spec.description = %q{Generate random but unique ids for your active record records.}
|
14
|
+
spec.summary = %q{Generate random but unique ids for your active record records.}
|
15
|
+
spec.homepage = "https://github.com/watu/random_unique_id"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files`.split($/)
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "activesupport", "> 3.2.0"
|
24
|
+
spec.add_dependency "activerecord", "> 3.2.0"
|
25
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Copyright © 2011, 2012, 2013, Watu
|
3
|
+
|
4
|
+
require_relative "test_helper"
|
5
|
+
|
6
|
+
require "random_unique_id"
|
7
|
+
|
8
|
+
ActiveRecord::Schema.define(version: 0) do
|
9
|
+
create_table :blogs do |t|
|
10
|
+
t.string :rid
|
11
|
+
end
|
12
|
+
add_index :blogs, :rid, unique: true
|
13
|
+
|
14
|
+
create_table :posts do |t|
|
15
|
+
t.string :rid
|
16
|
+
t.string :type
|
17
|
+
t.integer :blog_id
|
18
|
+
end
|
19
|
+
add_index :posts, :rid, unique: true
|
20
|
+
end
|
21
|
+
|
22
|
+
class Blog < ActiveRecord::Base
|
23
|
+
has_many :posts
|
24
|
+
has_random_unique_id
|
25
|
+
end
|
26
|
+
|
27
|
+
class Post < ActiveRecord::Base
|
28
|
+
belongs_to :blog
|
29
|
+
has_random_unique_id
|
30
|
+
end
|
31
|
+
|
32
|
+
class TextPost < Post
|
33
|
+
end
|
34
|
+
|
35
|
+
class ImagePost < Post
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
class RandomUniqueIdTest < MiniTest::Unit::TestCase
|
40
|
+
context "With a record with random id" do
|
41
|
+
setup { @text_post = TextPost.create! }
|
42
|
+
|
43
|
+
should "generate a random id" do
|
44
|
+
assert @text_post.rid
|
45
|
+
end
|
46
|
+
|
47
|
+
should "return random id as param" do
|
48
|
+
assert_equal @text_post.rid, @text_post.to_param
|
49
|
+
end
|
50
|
+
|
51
|
+
should "resolve random id collision" do
|
52
|
+
# Mock RandomUniqueId to return a collision on the first call, and hopefully a non collision on the second, expecting n to grow by one.
|
53
|
+
RandomUniqueId.expects(:generate_random_id).with(5).returns(@text_post.rid)
|
54
|
+
new_rid = @text_post.rid + "i"
|
55
|
+
RandomUniqueId.expects(:generate_random_id).with(6).returns(new_rid)
|
56
|
+
|
57
|
+
new_record = TextPost.create! # No exception should be raised.
|
58
|
+
assert_equal new_rid, new_record.rid
|
59
|
+
end
|
60
|
+
|
61
|
+
should "resolve random id collision in different classes of the same table (due to STI)" do
|
62
|
+
# Mock RandomUniqueId to return a collision on the first call, and hopefully a non collision on the second, expecting n to grow by one.
|
63
|
+
RandomUniqueId.expects(:generate_random_id).with(5).returns(@text_post.rid)
|
64
|
+
new_rid = @text_post.rid + "i"
|
65
|
+
RandomUniqueId.expects(:generate_random_id).with(6).returns(new_rid)
|
66
|
+
|
67
|
+
new_record = ImagePost.create! # No exception should be raised.
|
68
|
+
assert_equal new_rid, new_record.rid
|
69
|
+
end
|
70
|
+
|
71
|
+
should "have automatic *_rid= and *_rid methods" do
|
72
|
+
blog = Blog.create!
|
73
|
+
|
74
|
+
@text_post.blog_rid = blog.rid
|
75
|
+
@text_post.save!
|
76
|
+
|
77
|
+
assert_equal blog, @text_post.blog
|
78
|
+
assert_equal blog.rid, @text_post.blog_rid
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Copyright © 2013, Watu
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
|
6
|
+
require "simplecov"
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter "/test/"
|
9
|
+
end
|
10
|
+
|
11
|
+
require "minitest/autorun"
|
12
|
+
require "minitest/reporters"
|
13
|
+
MiniTest::Reporters.use!
|
14
|
+
|
15
|
+
# This class is here only to trick shoulda into attaching itself to MiniTest due to: https://github.com/thoughtbot/shoulda-context/issues/38
|
16
|
+
module ActiveSupport
|
17
|
+
class TestCase < MiniTest::Unit::TestCase
|
18
|
+
end
|
19
|
+
end
|
20
|
+
require "shoulda"
|
21
|
+
require "shoulda-context"
|
22
|
+
require "shoulda-matchers"
|
23
|
+
|
24
|
+
require "mocha/setup"
|
25
|
+
|
26
|
+
require "active_record"
|
27
|
+
ActiveRecord::Base.logger = Logger.new(STDERR)
|
28
|
+
ActiveRecord::Base.logger.level = Logger::WARN
|
29
|
+
ActiveRecord::Base.configurations = {"sqlite3" => {adapter: "sqlite3", database: ":memory:"}}
|
30
|
+
ActiveRecord::Base.establish_connection("sqlite3")
|
31
|
+
|
32
|
+
require "coveralls"
|
33
|
+
Coveralls.wear!
|
34
|
+
|
35
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
36
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: random_unique_id
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- J. Pablo Fernández
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>'
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>'
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>'
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>'
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.2.0
|
41
|
+
description: Generate random but unique ids for your active record records.
|
42
|
+
email:
|
43
|
+
- pupeno@watuapp.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- .travis.yml
|
50
|
+
- Gemfile
|
51
|
+
- LICENSE.txt
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- gemfiles/rails_3_2.Gemfile
|
55
|
+
- gemfiles/rails_4_0.Gemfile
|
56
|
+
- lib/random_unique_id.rb
|
57
|
+
- lib/random_unique_id/version.rb
|
58
|
+
- random_unique_id.gemspec
|
59
|
+
- test/random_unique_id_test.rb
|
60
|
+
- test/test_helper.rb
|
61
|
+
homepage: https://github.com/watu/random_unique_id
|
62
|
+
licenses:
|
63
|
+
- MIT
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.1.11
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: Generate random but unique ids for your active record records.
|
85
|
+
test_files:
|
86
|
+
- test/random_unique_id_test.rb
|
87
|
+
- test/test_helper.rb
|