record-locator 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +133 -0
- data/LICENSE.txt +20 -0
- data/README.md +68 -0
- data/Rakefile +41 -0
- data/VERSION +1 -0
- data/lib/record-locator-finder.rb +24 -0
- data/lib/record-locator-util.rb +39 -0
- data/lib/record-locator.rb +32 -0
- data/models/book.rb +6 -0
- data/record-locator.gemspec +63 -0
- data/spec/models/record-locator_spec.rb +84 -0
- data/spec/schema.rb +8 -0
- data/spec/spec_helper.rb +11 -0
- data/tddium.yml +3 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 80227723629775954056e7bbbd872273f5569f95
|
4
|
+
data.tar.gz: f1a00ed1597d89c3deab8721239d363a127fa295
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 15e7cb653b75d0aec890dcd18d2ebd0645bb13c57e93b361fe4934931d23fbc2565285659b6fcf611f9fb7ea19149a8f73a4486029a059b140026f06066910c2
|
7
|
+
data.tar.gz: 492a4d4c8792595baeba95986f1ff898986cfb6a2397b6fe36ab90d4a293f3c36f9178d2e3f4058f9262fa211813ef217d7c36d51234a3aea8ae3900c37eb3f6
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
actionmailer (3.2.15)
|
5
|
+
actionpack (= 3.2.15)
|
6
|
+
mail (~> 2.5.4)
|
7
|
+
actionpack (3.2.15)
|
8
|
+
activemodel (= 3.2.15)
|
9
|
+
activesupport (= 3.2.15)
|
10
|
+
builder (~> 3.0.0)
|
11
|
+
erubis (~> 2.7.0)
|
12
|
+
journey (~> 1.0.4)
|
13
|
+
rack (~> 1.4.5)
|
14
|
+
rack-cache (~> 1.2)
|
15
|
+
rack-test (~> 0.6.1)
|
16
|
+
sprockets (~> 2.2.1)
|
17
|
+
activemodel (3.2.15)
|
18
|
+
activesupport (= 3.2.15)
|
19
|
+
builder (~> 3.0.0)
|
20
|
+
activerecord (3.2.15)
|
21
|
+
activemodel (= 3.2.15)
|
22
|
+
activesupport (= 3.2.15)
|
23
|
+
arel (~> 3.0.2)
|
24
|
+
tzinfo (~> 0.3.29)
|
25
|
+
activeresource (3.2.15)
|
26
|
+
activemodel (= 3.2.15)
|
27
|
+
activesupport (= 3.2.15)
|
28
|
+
activesupport (3.2.15)
|
29
|
+
i18n (~> 0.6, >= 0.6.4)
|
30
|
+
multi_json (~> 1.0)
|
31
|
+
addressable (2.3.5)
|
32
|
+
arel (3.0.2)
|
33
|
+
builder (3.0.4)
|
34
|
+
diff-lcs (1.1.3)
|
35
|
+
erubis (2.7.0)
|
36
|
+
faraday (0.8.8)
|
37
|
+
multipart-post (~> 1.2.0)
|
38
|
+
git (1.2.6)
|
39
|
+
github_api (0.10.1)
|
40
|
+
addressable
|
41
|
+
faraday (~> 0.8.1)
|
42
|
+
hashie (>= 1.2)
|
43
|
+
multi_json (~> 1.4)
|
44
|
+
nokogiri (~> 1.5.2)
|
45
|
+
oauth2
|
46
|
+
hashie (2.0.5)
|
47
|
+
highline (1.6.20)
|
48
|
+
hike (1.2.3)
|
49
|
+
httpauth (0.2.0)
|
50
|
+
i18n (0.6.5)
|
51
|
+
jeweler (1.8.8)
|
52
|
+
builder
|
53
|
+
bundler (~> 1.0)
|
54
|
+
git (>= 1.2.5)
|
55
|
+
github_api (= 0.10.1)
|
56
|
+
highline (>= 1.6.15)
|
57
|
+
nokogiri (= 1.5.10)
|
58
|
+
rake
|
59
|
+
rdoc
|
60
|
+
journey (1.0.4)
|
61
|
+
json (1.8.1)
|
62
|
+
jwt (0.1.8)
|
63
|
+
multi_json (>= 1.5)
|
64
|
+
mail (2.5.4)
|
65
|
+
mime-types (~> 1.16)
|
66
|
+
treetop (~> 1.4.8)
|
67
|
+
mime-types (1.25)
|
68
|
+
multi_json (1.8.2)
|
69
|
+
multi_xml (0.5.5)
|
70
|
+
multipart-post (1.2.0)
|
71
|
+
nokogiri (1.5.10)
|
72
|
+
oauth2 (0.9.2)
|
73
|
+
faraday (~> 0.8)
|
74
|
+
httpauth (~> 0.2)
|
75
|
+
jwt (~> 0.1.4)
|
76
|
+
multi_json (~> 1.0)
|
77
|
+
multi_xml (~> 0.5)
|
78
|
+
rack (~> 1.2)
|
79
|
+
polyglot (0.3.3)
|
80
|
+
rack (1.4.5)
|
81
|
+
rack-cache (1.2)
|
82
|
+
rack (>= 0.4)
|
83
|
+
rack-ssl (1.3.3)
|
84
|
+
rack
|
85
|
+
rack-test (0.6.2)
|
86
|
+
rack (>= 1.0)
|
87
|
+
rails (3.2.15)
|
88
|
+
actionmailer (= 3.2.15)
|
89
|
+
actionpack (= 3.2.15)
|
90
|
+
activerecord (= 3.2.15)
|
91
|
+
activeresource (= 3.2.15)
|
92
|
+
activesupport (= 3.2.15)
|
93
|
+
bundler (~> 1.0)
|
94
|
+
railties (= 3.2.15)
|
95
|
+
railties (3.2.15)
|
96
|
+
actionpack (= 3.2.15)
|
97
|
+
activesupport (= 3.2.15)
|
98
|
+
rack-ssl (~> 1.3.2)
|
99
|
+
rake (>= 0.8.7)
|
100
|
+
rdoc (~> 3.4)
|
101
|
+
thor (>= 0.14.6, < 2.0)
|
102
|
+
rake (10.1.0)
|
103
|
+
rdoc (3.12.2)
|
104
|
+
json (~> 1.4)
|
105
|
+
rspec (2.5.0)
|
106
|
+
rspec-core (~> 2.5.0)
|
107
|
+
rspec-expectations (~> 2.5.0)
|
108
|
+
rspec-mocks (~> 2.5.0)
|
109
|
+
rspec-core (2.5.2)
|
110
|
+
rspec-expectations (2.5.0)
|
111
|
+
diff-lcs (~> 1.1.2)
|
112
|
+
rspec-mocks (2.5.0)
|
113
|
+
sprockets (2.2.2)
|
114
|
+
hike (~> 1.2)
|
115
|
+
multi_json (~> 1.0)
|
116
|
+
rack (~> 1.0)
|
117
|
+
tilt (~> 1.1, != 1.3.0)
|
118
|
+
sqlite3 (1.3.8)
|
119
|
+
thor (0.18.1)
|
120
|
+
tilt (1.4.1)
|
121
|
+
treetop (1.4.15)
|
122
|
+
polyglot
|
123
|
+
polyglot (>= 0.3.1)
|
124
|
+
tzinfo (0.3.38)
|
125
|
+
|
126
|
+
PLATFORMS
|
127
|
+
ruby
|
128
|
+
|
129
|
+
DEPENDENCIES
|
130
|
+
jeweler (~> 1.8.8)
|
131
|
+
rails (~> 3.2)
|
132
|
+
rspec (~> 2.5.0)
|
133
|
+
sqlite3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Abdul Barek and Ryan Alyn Porter
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Introduction
|
2
|
+
|
3
|
+
Remember the last time that you bought an airline ticket? You got an email with a
|
4
|
+
"[record locator](http://en.wikipedia.org/wiki/Record_locator)".
|
5
|
+
When you checked in for your flight, the airline didn't make you enter "23873498712098234095723469"
|
6
|
+
to get your boarding pass. You entered something like "FK92B9", and your name. The airline used
|
7
|
+
your name and that code to find the ID.
|
8
|
+
|
9
|
+
It's about usability. If humans ever need to type Active Record database IDs into a form for some
|
10
|
+
reason, then don't make them type a huge number, give them a short code. (An argument can be made
|
11
|
+
that if humans ever need to type record IDs into forms then you have bigger UX problems than the
|
12
|
+
record ID format and probably security problems also, and this is very true.)
|
13
|
+
|
14
|
+
One way to provide an easier ID to type is to use Base 36. It takes an integer and returns a really
|
15
|
+
short string that you can convert back to that integer again. And it's really easy to use with
|
16
|
+
Ruby:
|
17
|
+
|
18
|
+
12345678901.to_s(36).upcase
|
19
|
+
=> "5O6AQT1"
|
20
|
+
|
21
|
+
"5O6AQT1".to_i(36)
|
22
|
+
=> 12345678901
|
23
|
+
|
24
|
+
The problem with "5O6AQT1" is the second character. Is that an "O" or a "0"? And that last
|
25
|
+
character, is that a "1" or an "I"? And "Q" is a land mine too. It can look a lot like an "O" or
|
26
|
+
"0", especially if you can't control the typeface that it's printed in. A "5" can also look like an "S", or vice versa. And "B" and "8" can be confused in the same way.
|
27
|
+
|
28
|
+
What we really need is Base 27. We want to use Base 36, but without the potentially confusing
|
29
|
+
characters, "B", "8", "5", "S", "O", "0", "1", "I", or "Q". That's the Record Locator gem. I needed this gem and it
|
30
|
+
didn't exist, so I commissioned the impeccable services of Mr. Abdul Barek in Bangladesh, who did a
|
31
|
+
fantastic job.
|
32
|
+
|
33
|
+
# COMPATIBILITY WARNING
|
34
|
+
|
35
|
+
**WARNING:** This gem is **NOT** compatible with the
|
36
|
+
[PHP record locator](https://github.com/jakoubek/php-recordlocator) or the
|
37
|
+
[Perl record locator](http://search.cpan.org/~jesse/Number-RecordLocator-0.005/lib/Number/RecordLocator.pm)
|
38
|
+
libraries. Those libraries include potentially-confusing characters like "O" and "I". IDs encoded
|
39
|
+
with either of those libraries cannot be decoded using this library.
|
40
|
+
|
41
|
+
# How to install
|
42
|
+
|
43
|
+
Include the gem into your Gemfile:
|
44
|
+
|
45
|
+
gem 'record_locator', '1.0.0', :git => 'git@github.com:VenueDriver/record_locator.git'
|
46
|
+
|
47
|
+
Then run
|
48
|
+
|
49
|
+
bundle install
|
50
|
+
|
51
|
+
Suppose, you want to apply this encoding stuff on your Book Model's publisher_id then follow this way:
|
52
|
+
|
53
|
+
class Book < ActiveRecord::Base
|
54
|
+
extend RecordLocator
|
55
|
+
has_record_locator :publisher_id
|
56
|
+
end
|
57
|
+
|
58
|
+
Now restart your server.
|
59
|
+
|
60
|
+
**has_record_locator will expect Numeric field only (here publisher_id is Integer)**
|
61
|
+
|
62
|
+
From your ActiveRecord model object, You can get the encoded value by calling encoded_record_locator method:
|
63
|
+
|
64
|
+
@book.encoded_record_locator
|
65
|
+
|
66
|
+
You can find the ActiveRecord Model Object by passing encoded value, for example:
|
67
|
+
|
68
|
+
Blog.record_locator.find(params[:encoded_publisher_id])
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "record-locator"
|
18
|
+
gem.homepage = "http://github.com/VenueDriver/record-locator"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Use Base-27 encoding to shorten ID strings for easier data entry.}
|
21
|
+
gem.description = %Q{A Base-36 encoding for integer database IDs without potentially confusing character pairs like 5 and S, B and 8, I and 1, O and 0, or Q}
|
22
|
+
gem.email = "work@endymion.com"
|
23
|
+
gem.authors = ["Abdul Barek", "Ryan Alyn Porter"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
task :default => :spec
|
29
|
+
|
30
|
+
require 'rdoc/task'
|
31
|
+
Rake::RDocTask.new do |rdoc|
|
32
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
33
|
+
|
34
|
+
rdoc.rdoc_dir = 'rdoc'
|
35
|
+
rdoc.title = "record-locator #{version}"
|
36
|
+
rdoc.rdoc_files.include('README*')
|
37
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
38
|
+
end
|
39
|
+
|
40
|
+
require 'rspec/core/rake_task'
|
41
|
+
RSpec::Core::RakeTask.new('spec')
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Finder
|
2
|
+
|
3
|
+
def initialize(model,record_locator_field)
|
4
|
+
@model = model
|
5
|
+
@record_locator_field = record_locator_field
|
6
|
+
end
|
7
|
+
|
8
|
+
def find(id)
|
9
|
+
find_all(id).first
|
10
|
+
end
|
11
|
+
|
12
|
+
def find_all(id)
|
13
|
+
# for Rails > 4.0, use ActiveRecord where method
|
14
|
+
#@model.where("#{@record_locator_field}=?", Util::Base::decode(id.to_s))
|
15
|
+
|
16
|
+
# supported until rails 4.0 from rails 2.3
|
17
|
+
records = @model.find(:all, :conditions => "#{@record_locator_field}='#{Util::Base::decode(id.to_s)}'")
|
18
|
+
if records.empty?
|
19
|
+
records = @model.find(:all, :conditions => "#{@record_locator_field}='#{id}'")
|
20
|
+
end
|
21
|
+
return records
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Util
|
2
|
+
|
3
|
+
ENCODER = Hash.new do |h,k|
|
4
|
+
h[k] = Hash[ k.chars.map.enum_for(:each_with_index).to_a.map(&:reverse) ]
|
5
|
+
end
|
6
|
+
DECODER = Hash.new do |h,k|
|
7
|
+
h[k] = Hash[ k.chars.map.enum_for(:each_with_index).to_a ]
|
8
|
+
end
|
9
|
+
|
10
|
+
# 0 through 9 plus A through Z, without B8S5O0I1 or Q.
|
11
|
+
# "234679ACDEFGHJKLMNPRTUVWXYZ"
|
12
|
+
BASE27 = (('0'..'9').to_a + ('A'..'Z').to_a).delete_if{|char| char =~ /[B8S5O0I1Q]/}.join
|
13
|
+
|
14
|
+
class Base
|
15
|
+
|
16
|
+
def self.encode(value)
|
17
|
+
ring = Util::ENCODER[Util::BASE27]
|
18
|
+
base = Util::BASE27.length
|
19
|
+
result = []
|
20
|
+
until value == 0
|
21
|
+
result << ring[ value % base ]
|
22
|
+
value /= base
|
23
|
+
end
|
24
|
+
result.reverse.join
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.decode(string)
|
28
|
+
string = string.to_s
|
29
|
+
return string if string.split('').include?('1') || string.split('').include?('0') # as 0 and 1 are included into exceptional chars
|
30
|
+
ring = Util::DECODER[Util::BASE27]
|
31
|
+
base = Util::BASE27.length
|
32
|
+
string.reverse.chars.enum_for(:each_with_index).inject(0) do |sum,(char,i)|
|
33
|
+
sum + ring[char] * base**i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/record-locator-util')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/record-locator-finder')
|
3
|
+
|
4
|
+
module RecordLocator
|
5
|
+
|
6
|
+
def has_record_locator(reference_column)
|
7
|
+
@@record_locator_by = reference_column
|
8
|
+
self.send(:include, RecordLocator::InstanceMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_record_locator_field
|
12
|
+
@@record_locator_by
|
13
|
+
end
|
14
|
+
|
15
|
+
def record_locator
|
16
|
+
Finder.new(self,get_record_locator_field)
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
|
21
|
+
def record_locator_field
|
22
|
+
return self.class.to_s.constantize::get_record_locator_field
|
23
|
+
end
|
24
|
+
|
25
|
+
def encoded_record_locator
|
26
|
+
locator_value = self.send(record_locator_field)
|
27
|
+
Util::Base::encode(locator_value)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/models/book.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "record-locator"
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Abdul Barek", "Ryan Alyn Porter"]
|
12
|
+
s.date = "2013-11-14"
|
13
|
+
s.description = "A Base-36 encoding for integer database IDs without potentially confusing character pairs like 5 and S, B and 8, I and 1, O and 0, or Q"
|
14
|
+
s.email = "work@endymion.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"Gemfile",
|
21
|
+
"Gemfile.lock",
|
22
|
+
"LICENSE.txt",
|
23
|
+
"README.md",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/record-locator-finder.rb",
|
27
|
+
"lib/record-locator-util.rb",
|
28
|
+
"lib/record-locator.rb",
|
29
|
+
"models/book.rb",
|
30
|
+
"record-locator.gemspec",
|
31
|
+
"spec/models/record-locator_spec.rb",
|
32
|
+
"spec/schema.rb",
|
33
|
+
"spec/spec_helper.rb",
|
34
|
+
"tddium.yml"
|
35
|
+
]
|
36
|
+
s.homepage = "http://github.com/VenueDriver/record-locator"
|
37
|
+
s.licenses = ["MIT"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = "2.0.6"
|
40
|
+
s.summary = "Use Base-27 encoding to shorten ID strings for easier data entry."
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
s.specification_version = 4
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
|
+
s.add_development_dependency(%q<rails>, ["~> 3.2"])
|
47
|
+
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
48
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
|
49
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.8"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<rails>, ["~> 3.2"])
|
52
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
53
|
+
s.add_dependency(%q<rspec>, ["~> 2.5.0"])
|
54
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.8"])
|
55
|
+
end
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<rails>, ["~> 3.2"])
|
58
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
59
|
+
s.add_dependency(%q<rspec>, ["~> 2.5.0"])
|
60
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.8"])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '../../../lib/record-locator-util')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '../../../models/book')
|
5
|
+
|
6
|
+
describe 'RecordLocator' do
|
7
|
+
|
8
|
+
describe 'EncoderAndDecoder' do
|
9
|
+
|
10
|
+
it "Should produce an encoded ID that the original ID can be recovered from" do
|
11
|
+
100000.times do
|
12
|
+
original = rand(999999999999999)
|
13
|
+
encoded = Util::Base::encode(original)
|
14
|
+
decoded = Util::Base::decode(encoded)
|
15
|
+
original.should == decoded
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "Should not contain potentially-confusing characters (l,1,0,O,Q) after encode" do
|
20
|
+
100000.times do
|
21
|
+
original = rand(999999999999999)
|
22
|
+
encoded = Util::Base::encode(original)
|
23
|
+
encoded = encoded.split("")
|
24
|
+
encoded.include?('l').should == false
|
25
|
+
encoded.include?('1').should == false
|
26
|
+
encoded.include?('0').should == false
|
27
|
+
encoded.include?('O').should == false
|
28
|
+
encoded.include?('Q').should == false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "Should not produce any collisions." do
|
33
|
+
originals = {}
|
34
|
+
encodeds = {}
|
35
|
+
100000.times do
|
36
|
+
original = rand(999999)
|
37
|
+
next if originals.has_key? original
|
38
|
+
originals[original] = true
|
39
|
+
encoded = Util::Base::encode(original)
|
40
|
+
encodeds.has_key?(encoded).should == false
|
41
|
+
encodeds[encoded] = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
before(:each) do
|
48
|
+
@book = Book.find_or_create_by_publisher_id rand(999999999999999)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "Should return defined record locator filed" do
|
52
|
+
@book.record_locator_field.should == :publisher_id
|
53
|
+
end
|
54
|
+
|
55
|
+
it "Should not have record locator field nil" do
|
56
|
+
@book.encoded_record_locator.should_not be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "Should equal ActiveRecord locator decoded value with original ActiveRecord field value" do
|
60
|
+
@book.publisher_id.should == Util::Base::decode(Util::Base::encode(@book.publisher_id))
|
61
|
+
end
|
62
|
+
|
63
|
+
it "Should Return class type Finder" do
|
64
|
+
Book.record_locator.class.to_s.should == 'Finder'
|
65
|
+
end
|
66
|
+
|
67
|
+
it "Should Return class type Book" do
|
68
|
+
encoded_field = @book.encoded_record_locator
|
69
|
+
@book.class.should == Book.record_locator.find(encoded_field).class
|
70
|
+
end
|
71
|
+
|
72
|
+
it "Should return Original ActiveRecord Object found by defined encoded filed instead of Active record finder" do
|
73
|
+
encoded_field = @book.encoded_record_locator
|
74
|
+
@book.should === Book.record_locator.find(encoded_field)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "Should return Activerecord Object by passing normal id instead of passing encoded id" do
|
78
|
+
publisher_id = @book.publisher_id
|
79
|
+
|
80
|
+
@book.should === Book.record_locator.find(publisher_id)
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
end
|
data/spec/schema.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require "yaml"
|
4
|
+
require 'active_record'
|
5
|
+
require 'active_support'
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ':memory:')
|
9
|
+
load "spec/schema.rb"
|
10
|
+
ActiveRecord::Base.connection
|
11
|
+
end
|
data/tddium.yml
ADDED
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: record-locator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Abdul Barek
|
8
|
+
- Ryan Alyn Porter
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-11-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.2'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '3.2'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: sqlite3
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ~>
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 2.5.0
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 2.5.0
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: jeweler
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.8.8
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.8.8
|
70
|
+
description: A Base-36 encoding for integer database IDs without potentially confusing
|
71
|
+
character pairs like 5 and S, B and 8, I and 1, O and 0, or Q
|
72
|
+
email: work@endymion.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files:
|
76
|
+
- LICENSE.txt
|
77
|
+
- README.md
|
78
|
+
files:
|
79
|
+
- Gemfile
|
80
|
+
- Gemfile.lock
|
81
|
+
- LICENSE.txt
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- VERSION
|
85
|
+
- lib/record-locator-finder.rb
|
86
|
+
- lib/record-locator-util.rb
|
87
|
+
- lib/record-locator.rb
|
88
|
+
- models/book.rb
|
89
|
+
- record-locator.gemspec
|
90
|
+
- spec/models/record-locator_spec.rb
|
91
|
+
- spec/schema.rb
|
92
|
+
- spec/spec_helper.rb
|
93
|
+
- tddium.yml
|
94
|
+
homepage: http://github.com/VenueDriver/record-locator
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.0.6
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Use Base-27 encoding to shorten ID strings for easier data entry.
|
118
|
+
test_files: []
|