has_token_id 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ .DS_Store
4
+ coverage
5
+ Gemfile.lock
6
+ pkg/*
7
+ test/dummy_hooks/after_migrate.rb
8
+ test/dummy
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ before_script: "bundle exec dummier"
2
+
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.2
6
+ - 1.9.3
7
+ - rbx
8
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
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 [![Build Status](https://secure.travis-ci.org/citrus/has_token_id.png)](http://travis-ci.org/citrus/has_token_id) [![Dependency Status](https://gemnasium.com/citrus/has_token_id.png)](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,12 @@
1
+ require 'bundler'
2
+ require 'rake/testtask'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test' << 'lib'
8
+ t.pattern = 'test/**/*_test.rb'
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -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)
@@ -0,0 +1,3 @@
1
+ module HasTokenId
2
+ VERSION = "0.1.0"
3
+ end
@@ -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
@@ -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