has_token_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.
- data/.gitignore +8 -0
- data/.travis.yml +8 -0
- data/Gemfile +2 -0
- data/LICENSE +27 -0
- data/README.md +154 -0
- data/Rakefile +12 -0
- data/has_token_id.gemspec +30 -0
- data/lib/has_token_id/concern.rb +81 -0
- data/lib/has_token_id/table_definition.rb +14 -0
- data/lib/has_token_id/version.rb +3 -0
- data/lib/has_token_id.rb +31 -0
- data/test/dummy_hooks/after_migrate.sample +1 -0
- data/test/dummy_hooks/before_migrate.rb +20 -0
- data/test/support/test_case.rb +17 -0
- data/test/test_helper.rb +27 -0
- data/test/unit/concern_test.rb +157 -0
- data/test/unit/has_token_id_test.rb +17 -0
- data/test/unit/table_definition_test.rb +26 -0
- metadata +154 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright (c) 2011 Spencer Steffen and Citrus Media Group.
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice,
|
8
|
+
this list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
* Neither the name of Citrus Media Group nor the names of its
|
15
|
+
contributors may be used to endorse or promote products derived from this
|
16
|
+
software without specific prior written permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
19
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
20
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
22
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
23
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
24
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
25
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
26
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
# HasTokenId [](http://travis-ci.org/citrus/has_token_id) [](https://gemnasium.com/citrus/has_token_id)
|
2
|
+
|
3
|
+
Identify your active records with random tokens when you don't want your users to see a sequential ID.
|
4
|
+
|
5
|
+
|
6
|
+
------------------------------------------------------------------------------
|
7
|
+
Installation
|
8
|
+
------------------------------------------------------------------------------
|
9
|
+
|
10
|
+
Add has_token_id to your Gemfile like so:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'has_token_id', '~> 0.1.0'
|
14
|
+
```
|
15
|
+
|
16
|
+
Now run `bundle install` and you're good to go!
|
17
|
+
|
18
|
+
|
19
|
+
------------------------------------------------------------------------------
|
20
|
+
Usage
|
21
|
+
------------------------------------------------------------------------------
|
22
|
+
|
23
|
+
First, add a token to your model's table with a migration:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# Upgrade and existing table
|
27
|
+
class AddTokenToItems < ActiveRecord::Migration
|
28
|
+
add_column :items, :token, :string
|
29
|
+
end
|
30
|
+
|
31
|
+
# Add to a new table
|
32
|
+
class CreateItems < ActiveRecord::Migration
|
33
|
+
def change
|
34
|
+
create_table :items do |t|
|
35
|
+
t.token
|
36
|
+
t.string :name
|
37
|
+
|
38
|
+
t.timestamps
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
|
45
|
+
Now make sure your model knows to use it's token by calling `has_token_id`
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class Item < ActiveRecord::Base
|
49
|
+
has_token_id
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
That's basically it! Your Items will now know to use their token as their identifier.
|
54
|
+
|
55
|
+
Try it out in your `rails console`
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
@item = Item.create(:name => "Tokenz!")
|
59
|
+
#<Item id: 1, token: "Iccfa4bb1613e80097ba9495", name: "Tokenz!", created_at: "2012-01-26 20:17:13", updated_at: "2012-01-26 20:17:13">
|
60
|
+
@item.to_param
|
61
|
+
# Iccfa4bb1613e80097ba9495
|
62
|
+
@item == Item.find("Iccfa4bb1613e80097ba9495")
|
63
|
+
# true
|
64
|
+
```
|
65
|
+
|
66
|
+
|
67
|
+
------------------------------------------------------------------------------
|
68
|
+
Options
|
69
|
+
------------------------------------------------------------------------------
|
70
|
+
|
71
|
+
You can customize has_token_id by setting a few options. Here's the defaults:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
:prefix => nil, # if nil use first letter of class name
|
75
|
+
:length => 24,
|
76
|
+
:param_name => 'token',
|
77
|
+
:case_sensitive => false
|
78
|
+
```
|
79
|
+
|
80
|
+
|
81
|
+
Options can be set globally by overwriting the `HasTokenId.default_token_options`
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# config/initializers/has_token_id.rb
|
85
|
+
|
86
|
+
# for one option
|
87
|
+
HasTokenId.default_token_options[:prefix] = "OMG"
|
88
|
+
|
89
|
+
# for multiple options
|
90
|
+
HasTokenId.default_token_options.merge!(
|
91
|
+
:case_sensitive => true,
|
92
|
+
:length => 8
|
93
|
+
)
|
94
|
+
```
|
95
|
+
|
96
|
+
|
97
|
+
Options can also be set on a per-class level:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class List < ActiveRecord::Base
|
101
|
+
has_token_id :prefix => "LI", :length => 10
|
102
|
+
end
|
103
|
+
|
104
|
+
class Item < ActiveRecord::Base
|
105
|
+
has_token_id :prefix => "ITM"
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
|
110
|
+
------------------------------------------------------------------------------
|
111
|
+
Demo
|
112
|
+
------------------------------------------------------------------------------
|
113
|
+
|
114
|
+
Try out the demo to get a real clear idea of what has_token_id does.
|
115
|
+
|
116
|
+
```bash
|
117
|
+
git clone git://github.com/citrus/has_token_id.git
|
118
|
+
cd has_token_id
|
119
|
+
bundle install
|
120
|
+
bundle exec dummier
|
121
|
+
cd test/dummy
|
122
|
+
rails s
|
123
|
+
```
|
124
|
+
|
125
|
+
Now open your browser to [http://localhost:3000](http://localhost:3000)
|
126
|
+
|
127
|
+
|
128
|
+
------------------------------------------------------------------------------
|
129
|
+
Testing
|
130
|
+
------------------------------------------------------------------------------
|
131
|
+
|
132
|
+
Testing is done with [minitest](https://github.com/seattlerb/minitest), [minitest_should](https://github.com/citrus/minitest_should) and [dummier](https://github.com/citrus/dummier).
|
133
|
+
|
134
|
+
To get setup, run the following commands:
|
135
|
+
|
136
|
+
```bash
|
137
|
+
git clone git://github.com/citrus/has_token_id.git
|
138
|
+
cd has_token_id
|
139
|
+
bundle install
|
140
|
+
bundle exec dummier
|
141
|
+
```
|
142
|
+
|
143
|
+
Now run the tests with:
|
144
|
+
|
145
|
+
```bash
|
146
|
+
bundle exec rake
|
147
|
+
```
|
148
|
+
|
149
|
+
|
150
|
+
------------------------------------------------------------------------------
|
151
|
+
License
|
152
|
+
------------------------------------------------------------------------------
|
153
|
+
|
154
|
+
Copyright (c) 2011 - 2012 Spencer Steffen and Citrus, released under the New BSD License All rights reserved.
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "has_token_id/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
|
7
|
+
s.name = "has_token_id"
|
8
|
+
s.version = HasTokenId::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Spencer Steffen"]
|
11
|
+
s.email = ["spencer@citrusme.com"]
|
12
|
+
s.homepage = "https://github.com/citrus/has_token_id"
|
13
|
+
s.summary = %q{Identifies your active records with a random token.}
|
14
|
+
s.description = %q{Identifies your active records with a random token. For more information, please see the documentation.}
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features,lib/dummy_hooks}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency('activerecord', '>= 3.0.0')
|
22
|
+
s.add_dependency('activesupport', '>= 3.0.0')
|
23
|
+
|
24
|
+
s.add_development_dependency('rails', '>= 3.0.0')
|
25
|
+
s.add_development_dependency('dummier', '>= 0.3.0')
|
26
|
+
s.add_development_dependency('minitest', '>= 2.0.0')
|
27
|
+
s.add_development_dependency('minitest_should', '>= 0.3.1')
|
28
|
+
s.add_development_dependency('sqlite3', '>= 1.3.5')
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module HasTokenId
|
2
|
+
module Concern
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
validates :token, :presence => true, :uniqueness => true
|
8
|
+
before_validation :generate_token, :on => :create, :if => proc{|record| record.token.nil? }
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
attr_accessor :has_token_id_options
|
13
|
+
|
14
|
+
# Default options as well as an overwrite point so you can assign different defaults to different models
|
15
|
+
def default_token_options
|
16
|
+
return @default_token_options if @default_token_options
|
17
|
+
@default_token_options = HasTokenId.default_token_options
|
18
|
+
@default_token_options[:prefix] ||= self.name[0, 1]
|
19
|
+
@default_token_options
|
20
|
+
end
|
21
|
+
|
22
|
+
# Generates a unique token based on the options
|
23
|
+
def generate_unique_token
|
24
|
+
record, options = true, self.has_token_id_options
|
25
|
+
conditions = {}
|
26
|
+
while record
|
27
|
+
token = [ options[:prefix], Digest::SHA1.hexdigest((Time.now.to_i * rand()).to_s)].compact.join[0...options[:length].to_i]
|
28
|
+
conditions[options[:param_name].to_sym] = token
|
29
|
+
record = self.where(conditions).first
|
30
|
+
end
|
31
|
+
token
|
32
|
+
end
|
33
|
+
|
34
|
+
# Find by token ensuring case sensitivity
|
35
|
+
def find_by_case_sensitive_token(token)
|
36
|
+
where("#{token_with_table_name} = ?", token).first
|
37
|
+
end
|
38
|
+
|
39
|
+
# Find by token regardless of case
|
40
|
+
def find_by_case_insensitive_token(token)
|
41
|
+
where("lower(#{token_with_table_name}) = ?", token.downcase).first
|
42
|
+
end
|
43
|
+
|
44
|
+
# Find by token
|
45
|
+
def find_by_token(token)
|
46
|
+
send(has_token_id_options[:case_sensitive] ? :find_by_case_sensitive_token : :find_by_case_insensitive_token, token)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Find by token if the first param looks like a token, otherwise use super
|
50
|
+
def find(*args)
|
51
|
+
if args[0].is_a?(String) && args[0].length == has_token_id_options[:length]
|
52
|
+
record = find_by_token(args[0])
|
53
|
+
end
|
54
|
+
record || super(*args)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def token_with_table_name
|
60
|
+
[ table_name, has_token_id_options[:param_name] ].join(".")
|
61
|
+
end
|
62
|
+
|
63
|
+
end # ClassMethods
|
64
|
+
|
65
|
+
module InstanceMethods
|
66
|
+
|
67
|
+
def to_param
|
68
|
+
self.send(self.class.has_token_id_options[:param_name])
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def generate_token
|
74
|
+
self.token = self.class.generate_unique_token
|
75
|
+
end
|
76
|
+
|
77
|
+
end # InstanceMethods
|
78
|
+
|
79
|
+
end # Concern
|
80
|
+
|
81
|
+
end # HasTokenId
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'active_record/connection_adapters/abstract/schema_definitions'
|
2
|
+
|
3
|
+
module HasTokenId
|
4
|
+
module TableDefinition
|
5
|
+
|
6
|
+
def token(*args)
|
7
|
+
options = { :length => HasTokenId.default_token_options[:length] }.merge(args.extract_options!)
|
8
|
+
column(:token, :string, options.merge(:nil => false))
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, HasTokenId::TableDefinition)
|
data/lib/has_token_id.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'has_token_id/concern'
|
3
|
+
require 'has_token_id/table_definition'
|
4
|
+
|
5
|
+
module HasTokenId
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
|
9
|
+
base.instance_eval do
|
10
|
+
|
11
|
+
def has_token_id(options={})
|
12
|
+
self.send(:include, HasTokenId::Concern)
|
13
|
+
self.has_token_id_options = self.default_token_options.merge(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.default_token_options
|
21
|
+
@default_token_options ||= {
|
22
|
+
:prefix => nil, # if nil use first letter of class name
|
23
|
+
:length => 24,
|
24
|
+
:param_name => 'token',
|
25
|
+
:case_sensitive => false
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
end # Has Token
|
30
|
+
|
31
|
+
ActiveRecord::Base.send(:include, HasTokenId)
|
@@ -0,0 +1 @@
|
|
1
|
+
rake "db:migrate", :env => "development"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Generate an Item model
|
2
|
+
run "rails g scaffold item name:string"
|
3
|
+
|
4
|
+
# Add has_token_id to our Item model
|
5
|
+
gsub_file "app/models/item.rb", "end", %(
|
6
|
+
has_token_id
|
7
|
+
|
8
|
+
end)
|
9
|
+
|
10
|
+
# Replace the delete link with a button since we won't have js in the demo
|
11
|
+
gsub_file "app/views/items/index.html.erb", %(link_to 'Destroy'), %(button_to 'Destroy')
|
12
|
+
|
13
|
+
# Ensure our migration is using our `token` TableDefinition
|
14
|
+
@migration = File.basename(Dir[File.expand_path("db/migrate/*.rb", destination_path)].last)
|
15
|
+
gsub_file File.join("db/migrate/", @migration), "t.string :name", "t.token\n t.string :name"
|
16
|
+
|
17
|
+
# Route items#index as the root path
|
18
|
+
gsub_file "config/routes.rb", "resources :items", %(
|
19
|
+
resources :items
|
20
|
+
root :to => "items#index")
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class MiniTest::Should::TestCase
|
2
|
+
|
3
|
+
# Borrowed from thor .. thanks wycats! :)
|
4
|
+
def capture(stream)
|
5
|
+
begin
|
6
|
+
stream = stream.to_s
|
7
|
+
eval "$#{stream} = StringIO.new"
|
8
|
+
yield
|
9
|
+
result = eval("$#{stream}").string
|
10
|
+
ensure
|
11
|
+
eval("$#{stream} = #{stream.upcase}")
|
12
|
+
end
|
13
|
+
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
|
3
|
+
gem "minitest"
|
4
|
+
|
5
|
+
begin
|
6
|
+
require "simplecov"
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter do |source_file|
|
9
|
+
source_file.filename =~ /dummy/
|
10
|
+
end
|
11
|
+
end
|
12
|
+
rescue LoadError
|
13
|
+
end
|
14
|
+
|
15
|
+
env = File.expand_path("../dummy/config/environment.rb", __FILE__)
|
16
|
+
if File.exists?(env)
|
17
|
+
require env
|
18
|
+
else
|
19
|
+
raise LoadError, "Please create the dummy app before running tests. Try running `bundle exec dummier`"
|
20
|
+
end
|
21
|
+
|
22
|
+
require "rails/test_help"
|
23
|
+
require "minitest/autorun"
|
24
|
+
require "minitest/should"
|
25
|
+
require "support/test_case"
|
26
|
+
|
27
|
+
Rails.backtrace_cleaner.remove_silencers!
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
# We'll test the test/dummy/app/item.rb model
|
4
|
+
|
5
|
+
class ConcernTest < MiniTest::Should::TestCase
|
6
|
+
|
7
|
+
setup do
|
8
|
+
# remove all items
|
9
|
+
Item.destroy_all
|
10
|
+
# reset to defaults
|
11
|
+
Item.has_token_id_options.merge!(Item.default_token_options)
|
12
|
+
end
|
13
|
+
|
14
|
+
should "respond to has_token_id" do
|
15
|
+
assert Item.respond_to?(:has_token_id)
|
16
|
+
end
|
17
|
+
|
18
|
+
should "set it's token" do
|
19
|
+
@item = Item.new(:name => "Something")
|
20
|
+
assert @item.valid?
|
21
|
+
assert !@item.token.nil?
|
22
|
+
assert @item.save
|
23
|
+
end
|
24
|
+
|
25
|
+
should "only set it's token once" do
|
26
|
+
@item = Item.new(:name => "Something")
|
27
|
+
assert @item.valid?
|
28
|
+
token = @item.token
|
29
|
+
assert !token.nil?
|
30
|
+
@item.name = "Something else"
|
31
|
+
assert @item.valid?
|
32
|
+
assert_equal token, @item.token
|
33
|
+
end
|
34
|
+
|
35
|
+
should "join token with table name when searching for record" do
|
36
|
+
assert_equal "items.token", Item.send(:token_with_table_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with an existing item" do
|
40
|
+
|
41
|
+
setup do
|
42
|
+
@item = Item.create(:name => "Blue Cheese Burger")
|
43
|
+
end
|
44
|
+
|
45
|
+
should "assume token prefix" do
|
46
|
+
assert_equal "I", @item.token[0, 1]
|
47
|
+
end
|
48
|
+
|
49
|
+
should "have default options" do
|
50
|
+
opts = { :prefix => "I", :length => 24, :param_name => "token", :case_sensitive => false }
|
51
|
+
assert_equal opts, Item.has_token_id_options
|
52
|
+
end
|
53
|
+
|
54
|
+
should "have proper token length" do
|
55
|
+
assert_equal Item.has_token_id_options[:length], @item.token.length
|
56
|
+
end
|
57
|
+
|
58
|
+
should "have token as to_param" do
|
59
|
+
assert_equal @item.to_param, @item.token
|
60
|
+
end
|
61
|
+
|
62
|
+
should "find by token" do
|
63
|
+
assert_equal @item, Item.find(@item.token)
|
64
|
+
end
|
65
|
+
|
66
|
+
should "work with token finder method" do
|
67
|
+
assert Item.find_by_token(@item.token)
|
68
|
+
end
|
69
|
+
|
70
|
+
should "work with !bang token finder method" do
|
71
|
+
assert Item.find_by_token!(@item.token)
|
72
|
+
end
|
73
|
+
|
74
|
+
should "return nil from token finder method when record is not found" do
|
75
|
+
assert_equal nil, Item.find_by_token("invalid")
|
76
|
+
end
|
77
|
+
|
78
|
+
should "raise activerecord not found from !bang token finder method when record is not found" do
|
79
|
+
assert_raises ActiveRecord::RecordNotFound do
|
80
|
+
Item.find_by_token!("invalid")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when case sensitivity is disabled" do
|
85
|
+
|
86
|
+
setup do
|
87
|
+
Item.has_token_id_options[:case_sensitive] = false
|
88
|
+
end
|
89
|
+
|
90
|
+
should "find by token" do
|
91
|
+
assert_equal @item, Item.find(@item.token)
|
92
|
+
end
|
93
|
+
|
94
|
+
should "find by token even if it's all uppercase" do
|
95
|
+
assert_equal @item, Item.find(@item.token.upcase)
|
96
|
+
end
|
97
|
+
|
98
|
+
should "find by token even if it's all lowercase" do
|
99
|
+
assert_equal @item, Item.find(@item.token.downcase)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
context "when case sensitivity is enabled" do
|
105
|
+
|
106
|
+
setup do
|
107
|
+
Item.has_token_id_options[:case_sensitive] = true
|
108
|
+
end
|
109
|
+
|
110
|
+
should "find by token" do
|
111
|
+
assert_equal @item, Item.find(@item.token)
|
112
|
+
end
|
113
|
+
|
114
|
+
should "not find by token if it's all uppercase" do
|
115
|
+
assert_raises ActiveRecord::RecordNotFound do
|
116
|
+
Item.find(@item.token.upcase)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
should "find by token even if it's all lowercase" do
|
121
|
+
assert_raises ActiveRecord::RecordNotFound do
|
122
|
+
assert Item.find(@item.token.downcase)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
context "with a long token" do
|
131
|
+
|
132
|
+
setup do
|
133
|
+
Item.has_token_id_options[:length] = 40
|
134
|
+
@item = Item.create(:name => "Bacon Cheese Burger")
|
135
|
+
end
|
136
|
+
|
137
|
+
should "have long token" do
|
138
|
+
assert_equal 40, @item.token.length
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
context "with long prefix" do
|
144
|
+
|
145
|
+
setup do
|
146
|
+
Item.has_token_id_options.update(:prefix => "item-", :length => 40)
|
147
|
+
@item = Item.create(:name => "Bacon Cheese Burger")
|
148
|
+
end
|
149
|
+
|
150
|
+
should "account for longer prefixes" do
|
151
|
+
assert_equal 40, @item.token.length
|
152
|
+
assert_match /^item-(.*)/, @item.token
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class HasTokenIdIdTest < MiniTest::Should::TestCase
|
4
|
+
|
5
|
+
should "have version" do
|
6
|
+
assert_equal String, HasTokenId::VERSION.class
|
7
|
+
end
|
8
|
+
|
9
|
+
should "include HasTokenId" do
|
10
|
+
assert ActiveRecord::Base.included_modules.include?(HasTokenId)
|
11
|
+
end
|
12
|
+
|
13
|
+
should "have has_token_id method" do
|
14
|
+
assert ActiveRecord::Base.respond_to?(:has_token_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TableDefinitionTest < MiniTest::Should::TestCase
|
4
|
+
|
5
|
+
setup do
|
6
|
+
@migration = ActiveRecord::Migration.new
|
7
|
+
@definition = ActiveRecord::ConnectionAdapters::TableDefinition.new(@migration)
|
8
|
+
end
|
9
|
+
|
10
|
+
should "include token as a migration table definition" do
|
11
|
+
assert @definition.respond_to?(:token)
|
12
|
+
end
|
13
|
+
|
14
|
+
should "token definition should be the same as a string column named token" do
|
15
|
+
capture(:stdout) {
|
16
|
+
assert_equal @definition.column(:token, :string), @definition.token
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
should "token definition should include custom options" do
|
21
|
+
capture(:stdout) {
|
22
|
+
assert_equal @definition.column(:token, :string, :length => 8), @definition.token(:length => 8)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: has_token_id
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Spencer Steffen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-27 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: &70098471332260 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70098471332260
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
requirement: &70098471329600 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70098471329600
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rails
|
38
|
+
requirement: &70098471329120 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 3.0.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70098471329120
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: dummier
|
49
|
+
requirement: &70098471328580 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.3.0
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70098471328580
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: minitest
|
60
|
+
requirement: &70098471327820 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 2.0.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70098471327820
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest_should
|
71
|
+
requirement: &70098471327140 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.3.1
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70098471327140
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: sqlite3
|
82
|
+
requirement: &70098471326400 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 1.3.5
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70098471326400
|
91
|
+
description: Identifies your active records with a random token. For more information,
|
92
|
+
please see the documentation.
|
93
|
+
email:
|
94
|
+
- spencer@citrusme.com
|
95
|
+
executables: []
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files: []
|
98
|
+
files:
|
99
|
+
- .gitignore
|
100
|
+
- .travis.yml
|
101
|
+
- Gemfile
|
102
|
+
- LICENSE
|
103
|
+
- README.md
|
104
|
+
- Rakefile
|
105
|
+
- has_token_id.gemspec
|
106
|
+
- lib/has_token_id.rb
|
107
|
+
- lib/has_token_id/concern.rb
|
108
|
+
- lib/has_token_id/table_definition.rb
|
109
|
+
- lib/has_token_id/version.rb
|
110
|
+
- test/dummy_hooks/after_migrate.sample
|
111
|
+
- test/dummy_hooks/before_migrate.rb
|
112
|
+
- test/support/test_case.rb
|
113
|
+
- test/test_helper.rb
|
114
|
+
- test/unit/concern_test.rb
|
115
|
+
- test/unit/has_token_id_test.rb
|
116
|
+
- test/unit/table_definition_test.rb
|
117
|
+
homepage: https://github.com/citrus/has_token_id
|
118
|
+
licenses: []
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
hash: -556802150054861821
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
hash: -556802150054861821
|
141
|
+
requirements: []
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 1.8.10
|
144
|
+
signing_key:
|
145
|
+
specification_version: 3
|
146
|
+
summary: Identifies your active records with a random token.
|
147
|
+
test_files:
|
148
|
+
- test/dummy_hooks/after_migrate.sample
|
149
|
+
- test/dummy_hooks/before_migrate.rb
|
150
|
+
- test/support/test_case.rb
|
151
|
+
- test/test_helper.rb
|
152
|
+
- test/unit/concern_test.rb
|
153
|
+
- test/unit/has_token_id_test.rb
|
154
|
+
- test/unit/table_definition_test.rb
|