quick_short 0.0.1 → 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.
- data/lib/quick_short/duplicate_prefix.rb +13 -0
- data/lib/quick_short/has_short_id.rb +36 -0
- data/lib/quick_short/no_such_prefix.rb +12 -0
- data/lib/quick_short/short_id.rb +41 -21
- data/lib/quick_short/version.rb +1 -1
- data/lib/quick_short.rb +50 -6
- data/spec/spec_helper.rb +17 -0
- metadata +37 -55
@@ -0,0 +1,13 @@
|
|
1
|
+
module QuickShort
|
2
|
+
|
3
|
+
class DuplicatePrefix < StandardError
|
4
|
+
|
5
|
+
# When trying to register the same key twice
|
6
|
+
def initialize(prefix)
|
7
|
+
klass = QuickShort.short_id_prefixes[prefix]
|
8
|
+
super "Duplicate prefix: #{prefix} (already assigned to #{klass.name})"
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module QuickShort
|
2
|
+
|
3
|
+
# A mixin for registering a class with short_ids
|
4
|
+
module HasShortId
|
5
|
+
|
6
|
+
# Register this class with QuickShort with a certain
|
7
|
+
# prefix. With prefix 'a', will generate ids like 'a-lksdjf'
|
8
|
+
# @param [String] prefix - The prefix for this class
|
9
|
+
def has_short_id(prefix)
|
10
|
+
send(:include, InstanceMethods)
|
11
|
+
if QuickShort.short_id_prefixes.has_key?(prefix)
|
12
|
+
raise QuickShort::DuplicatePrefix.new(prefix)
|
13
|
+
else
|
14
|
+
QuickShort.short_id_prefixes[prefix] = self
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Instance methods for things that has_short_id
|
20
|
+
module InstanceMethods
|
21
|
+
|
22
|
+
# Get the short id (expects a method named #id to be
|
23
|
+
# defined on this class)
|
24
|
+
# @return [String] the generated short id
|
25
|
+
def short_id
|
26
|
+
if id
|
27
|
+
prefix = QuickShort.short_id_prefixes.key(self.class)
|
28
|
+
"#{prefix}-#{QuickShort::ShortId.encode(id)}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/lib/quick_short/short_id.rb
CHANGED
@@ -1,30 +1,50 @@
|
|
1
1
|
module QuickShort
|
2
2
|
|
3
|
+
# This module handles the actual encoding and decoding
|
4
|
+
# of the IDs
|
3
5
|
module ShortId
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
# This is the sequence of characters we use to encode the ID
|
8
|
+
# Note: We cut out vowels to avoid shortened strings from mistakenly
|
9
|
+
# forming words
|
10
|
+
DefaultAlphabet = 'bcdfghjklmnpqrstvwxyz0123456789BCDFGHJKLMNPQRSTVWXYZ'
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
# Get the alphabet to use
|
15
|
+
def alphabet
|
16
|
+
@alphabet ||= DefaultAlphabet
|
13
17
|
end
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
|
19
|
+
# Encode a numeric ID
|
20
|
+
# @param [Fixnum] id - the ID to encode
|
21
|
+
# @return [String] the encoded ID
|
22
|
+
def encode(id)
|
23
|
+
alpha = ''
|
24
|
+
while id != 0
|
25
|
+
alpha = alphabet[id % alphabet.length].chr + alpha
|
26
|
+
id /= alphabet.length
|
27
|
+
end
|
28
|
+
alpha
|
29
|
+
end
|
30
|
+
|
31
|
+
# Decode an ID created with encode
|
32
|
+
# @param [String] the ID to decode
|
33
|
+
# @return [Fixnum] the decoded ID
|
34
|
+
def decode(alpha)
|
35
|
+
alpha = alpha.dup; id = 0
|
36
|
+
0.upto(alpha.length - 1) do |i|
|
37
|
+
letter = alpha[alpha.length - 1]
|
38
|
+
alphabet_index = alphabet.index letter
|
39
|
+
unless alphabet_index # bad character present?
|
40
|
+
raise ArgumentError.new("Character not in Alphabet: #{letter}")
|
41
|
+
end
|
42
|
+
id += alphabet_index * (alphabet.length ** i)
|
43
|
+
alpha.chop!
|
44
|
+
end
|
45
|
+
id
|
26
46
|
end
|
27
|
-
|
47
|
+
|
28
48
|
end
|
29
49
|
|
30
50
|
end
|
data/lib/quick_short/version.rb
CHANGED
data/lib/quick_short.rb
CHANGED
@@ -1,10 +1,54 @@
|
|
1
1
|
module QuickShort
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
autoload :ShortId, File.dirname(__FILE__) + '/quick_short/short_id'
|
4
|
+
autoload :HasShortId, File.dirname(__FILE__) + '/quick_short/has_short_id'
|
5
|
+
|
6
|
+
autoload :DuplicatePrefix, File.dirname(__FILE__) + '/quick_short/duplicate_prefix'
|
7
|
+
autoload :NoSuchPrefix, File.dirname(__FILE__) + '/quick_short/no_such_prefix'
|
8
|
+
|
9
|
+
autoload :VERSION, File.dirname(__FILE__) + '/quick_short/version'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# The current mapping of short_id_prefixes
|
14
|
+
# @return [Hash] the mapping
|
15
|
+
def short_id_prefixes
|
16
|
+
@prefixes ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
# A convenient alias for #find which locates the class and calls find(id)
|
20
|
+
# @param [String] short_id - the short id to look up
|
21
|
+
def find(short_id)
|
22
|
+
lookup(short_id) do |klass, id|
|
23
|
+
klass.find id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# A convenient alias for #find_by_id which locates the class and calls
|
28
|
+
# find_by_id(id)
|
29
|
+
# @param [String] short_id - the short id to look up
|
30
|
+
def find_by_short_id(short_id)
|
31
|
+
lookup(short_id) do |klass, id|
|
32
|
+
klass.find_by_id id
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Look up a short id, and yield [klass, id] to a block, or return as array
|
37
|
+
# @param [String] short_id - the short id to look up
|
38
|
+
def lookup(short_id)
|
39
|
+
prefix, short_id = short_id.split('-', 2)
|
40
|
+
if klass = short_id_prefixes[prefix]
|
41
|
+
id = QuickShort::ShortId.decode(short_id)
|
42
|
+
if block_given?
|
43
|
+
yield klass, id # return result
|
44
|
+
else
|
45
|
+
[klass, id] # otherwise, return [klass, id]
|
46
|
+
end
|
47
|
+
else
|
48
|
+
raise NoSuchPrefix.new(prefix)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
7
53
|
|
8
|
-
require 'lib/quick_short/short_id.rb'
|
9
|
-
|
10
54
|
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
rescue LoadError
|
5
|
+
# oh well
|
6
|
+
end
|
7
|
+
|
8
|
+
# Load
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'quick_short')
|
10
|
+
|
11
|
+
# ensure that a number makes a successful round trip and then
|
12
|
+
# return its encoding
|
13
|
+
def ensure_numeric_round_trip(number)
|
14
|
+
encoding = QuickShort::ShortId.encode(number)
|
15
|
+
QuickShort::ShortId.decode(encoding).should == number
|
16
|
+
encoding
|
17
|
+
end
|
metadata
CHANGED
@@ -1,82 +1,64 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: quick_short
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 1
|
10
|
-
version: 0.0.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- John Crepezzi
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-01-12 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: rspec
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &22384760 !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
33
22
|
type: :development
|
34
|
-
|
35
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *22384760
|
25
|
+
description: quick_short is a really awesome way to generate short URLs (especially
|
26
|
+
for local resources)
|
36
27
|
email: john@crepezzi.com
|
37
28
|
executables: []
|
38
|
-
|
39
29
|
extensions: []
|
40
|
-
|
41
30
|
extra_rdoc_files: []
|
42
|
-
|
43
|
-
|
44
|
-
- lib/quick_short/
|
31
|
+
files:
|
32
|
+
- lib/quick_short/has_short_id.rb
|
33
|
+
- lib/quick_short/no_such_prefix.rb
|
45
34
|
- lib/quick_short/version.rb
|
35
|
+
- lib/quick_short/duplicate_prefix.rb
|
36
|
+
- lib/quick_short/short_id.rb
|
46
37
|
- lib/quick_short.rb
|
47
|
-
|
38
|
+
- spec/spec_helper.rb
|
48
39
|
homepage: http://seejohnrun.github.com/quick_short/
|
49
40
|
licenses: []
|
50
|
-
|
51
41
|
post_install_message:
|
52
42
|
rdoc_options: []
|
53
|
-
|
54
|
-
require_paths:
|
43
|
+
require_paths:
|
55
44
|
- lib
|
56
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
46
|
none: false
|
58
|
-
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
|
62
|
-
|
63
|
-
- 0
|
64
|
-
version: "0"
|
65
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
52
|
none: false
|
67
|
-
requirements:
|
68
|
-
- -
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
|
71
|
-
segments:
|
72
|
-
- 0
|
73
|
-
version: "0"
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
74
57
|
requirements: []
|
75
|
-
|
76
58
|
rubyforge_project: quick-short
|
77
|
-
rubygems_version: 1.
|
59
|
+
rubygems_version: 1.8.10
|
78
60
|
signing_key:
|
79
61
|
specification_version: 3
|
80
62
|
summary: Rails Short URL Library - Employs Magic
|
81
|
-
test_files:
|
82
|
-
|
63
|
+
test_files:
|
64
|
+
- spec/spec_helper.rb
|