record-locator 0.0.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/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: []
|