route_counter 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1fc94b92228e7bbabc32aac5993cc9c40d419b05
4
+ data.tar.gz: aeb549b53956c26c7c6b34d6ec83491c184deddc
5
+ SHA512:
6
+ metadata.gz: 370d759b06abd2057c2e855b55c83dd2913bda8aff7813c4fcbb8972c498cab8befa68f83a9f01a3acce5abc017821307c1e280d2d9cbfa15890155d37495892
7
+ data.tar.gz: 404f635724b19c567538865396b2e85edb3b96033894c15d491f77848c2d15e78ee7cb98c829b9db6b1814ed6cc843d541d13634d6910b865882d6937798efa3
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in route_counter.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,82 @@
1
+ # RouteCounter
2
+
3
+ When you want to know how much your routes are being used.
4
+
5
+ This is particularly useful if you are wondering if they are used at all.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'route_counter'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install route_counter
20
+
21
+ Enable the recording in an initializer and insert the middleware:
22
+
23
+ ```ruby
24
+ RouteCounter.config.enabled = true
25
+ Rails.application.config.middleware.use RouteCounter::Middleware
26
+ ```
27
+
28
+ Add to Rakefile:
29
+
30
+ ```ruby
31
+ require "route_counter/tasks"
32
+ ```
33
+
34
+ ## Usage
35
+
36
+
37
+ Check what's been used.
38
+
39
+ ```bash
40
+ $ bundle exec rake routes:count:local
41
+ ```
42
+
43
+ All of this gets stored on your disk. If you want to clear it out.
44
+
45
+ ```bash
46
+ $ bundle exec rake route_counter:local:clear
47
+ ```
48
+
49
+ ## Global Usage
50
+
51
+ You might want to see the counts across your servers.
52
+ This will use Redis to aggregate info from across all of them.
53
+ First, you'll need to tell it where Redis is:
54
+
55
+ ```ruby
56
+ RouteCounter.config.redis = Redis.new(connection_hash)
57
+ ```
58
+
59
+ Then, you can clear out the remote store.
60
+ Or not to be cumulative to last time you took a snapshot
61
+
62
+ ```bash
63
+ $ bundle exec rake route_counter:global:clear
64
+ ```
65
+
66
+ Then take a snapshot. You can do this in parallel on all of your servers (with Capistrano for example).
67
+
68
+ ```bash
69
+ $ bundle exec rake route_counter:snapshot
70
+ ```
71
+
72
+ Then on one of the servers you can run to use the global numbers
73
+
74
+ ```bash
75
+ $ bundle exec rake routes:count:global
76
+ ```
77
+
78
+ ## TODO
79
+
80
+ * could make a middleware (or config option) that wrote directly to Redis
81
+ * should it record more info about the request?
82
+ * configurable error handler
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,24 @@
1
+ require "route_counter/version"
2
+
3
+ module RouteCounter
4
+ autoload :Config, 'route_counter/config'
5
+ autoload :ConsoleFormatter, 'route_counter/console_formatter'
6
+ autoload :FileRecorder, 'route_counter/file_recorder'
7
+ autoload :Middleware, 'route_counter/middleware'
8
+ autoload :RedisRecorder, 'route_counter/redis_recorder'
9
+ autoload :Snapshot, 'route_counter/snapshot'
10
+ autoload :Util, 'route_counter/util'
11
+
12
+ class << self
13
+ def config
14
+ @config ||= RouteCounter::Config.new
15
+ end
16
+
17
+ protected
18
+
19
+ def reset
20
+ # mostly for tests, resets eveything
21
+ @config = nil
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ module RouteCounter
2
+ class Config
3
+ attr_writer :directory, :enabled, :redis
4
+
5
+ def directory
6
+ @directory ||= File.join(Dir.home, "route_counter")
7
+ end
8
+
9
+ def enabled
10
+ !!@enabled
11
+ end
12
+ alias :enabled? :enabled
13
+
14
+ def redis
15
+ return @redis if @redis
16
+ require 'redis'
17
+ @redis = Redis.new
18
+ end
19
+
20
+ def error!(e)
21
+ # TODO: not worth it to crash but should log. allow settable
22
+ if defined?(Rails)
23
+ Rails.logger.error(e)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,84 @@
1
+ require 'action_dispatch/routing/inspector'
2
+
3
+ module RouteCounter
4
+ class ConsoleFormatter # like ActionDispatch::Routing::ConsoleFormatter
5
+ class << self
6
+ def puts!(recorder_klass)
7
+ # from railties/routes.rake
8
+ all_routes = Rails.application.routes.routes
9
+ inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes)
10
+ path_hash = recorder_klass.actions_visited
11
+ formatter = RouteCounter::ConsoleFormatter.new(path_hash)
12
+ puts inspector.format(formatter, ENV['CONTROLLER'])
13
+ end
14
+ end
15
+
16
+ def initialize(path_hash)
17
+ @buffer = []
18
+ @path_hash = path_hash || {}
19
+ end
20
+
21
+ def result
22
+ @buffer.join("\n")
23
+ end
24
+
25
+ def section_title(title)
26
+ @buffer << "\n#{title}:"
27
+ end
28
+
29
+ def section(routes)
30
+ @buffer << draw_section(routes)
31
+ end
32
+
33
+ def header(routes)
34
+ @buffer << draw_header(routes)
35
+ end
36
+
37
+ def no_routes
38
+ @buffer << <<-MESSAGE.strip_heredoc
39
+ You don't have any routes defined!
40
+
41
+ Please add some routes in config/routes.rb.
42
+
43
+ For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html.
44
+ MESSAGE
45
+ end
46
+
47
+ private
48
+ def draw_section(routes)
49
+ count_width, name_width, verb_width, path_width = widths(routes)
50
+
51
+ routes.map do |r|
52
+ "#{count_for_route(r).ljust(count_width)} #{r[:name].ljust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
53
+ end
54
+ end
55
+
56
+ def draw_header(routes)
57
+ count_width, name_width, verb_width, path_width = widths(routes)
58
+
59
+ "#{"Count".rjust(count_width)} #{"Prefix".ljust(name_width)} #{"Verb".ljust(verb_width)} #{"URI Pattern".ljust(path_width)} Controller#Action"
60
+ end
61
+
62
+ def widths(routes)
63
+ [ max_count_width,
64
+ routes.map { |r| r[:name].length }.max,
65
+ routes.map { |r| r[:verb].length }.max,
66
+ routes.map { |r| r[:path].length }.max]
67
+ end
68
+
69
+ def max_count_width
70
+ @max_count_width ||= [@path_hash.values.max.to_s.length, "Count".length].max
71
+ end
72
+
73
+ def count_for_route(r)
74
+ has_action = r[:reqs].to_s
75
+ return "~" unless has_action.include?("#")
76
+ count = 0
77
+ @path_hash.each do |action, num|
78
+ next unless has_action.start_with?(action)
79
+ count += num
80
+ end
81
+ count.to_s
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,127 @@
1
+ require 'fileutils'
2
+ require 'monitor'
3
+
4
+ # A recorder implements these class methods
5
+ # * action_visited(controller_name, action_name) : record that it was visited
6
+ # * actions_visited : returns hash of url => count
7
+ # * rotate! : backup what was recorded and start counting again. returns hash.
8
+ # * clear! : clear everything out
9
+
10
+ module RouteCounter
11
+ class FileRecorder
12
+ class << self
13
+
14
+ def parent_directory
15
+ RouteCounter.config.directory
16
+ end
17
+
18
+ def current_directory
19
+ File.join(parent_directory, 'current')
20
+ end
21
+
22
+ def read_directory(root)
23
+ out = {}
24
+ Dir[ File.join(root, '**', '*') ].each do |file|
25
+ next if File.directory?(file)
26
+ hits = File.size(file) # each should be 1 byte
27
+ action_name = File.basename(file)
28
+ controller_name = File.dirname(file)
29
+ controller_name.gsub!("#{root}/", '')
30
+ key = "#{controller_name}##{action_name}"
31
+ out[key] ||= 0
32
+ out[key] += hits
33
+ end
34
+ out
35
+ end
36
+
37
+ def action_visited(controller_name, action_name)
38
+ # write down it was visited
39
+ file_path = File.join(File.join(current_directory, controller_name, action_name))
40
+ logdev = LogDevice.new(file_path)
41
+ logdev.write('X')
42
+ logdev.close
43
+ end
44
+
45
+ def actions_visited
46
+ # returns what was visited and counts
47
+ read_directory(current_directory)
48
+ end
49
+
50
+ def rotate!
51
+ # lock the current one and return the visited
52
+ alt_directory = File.join(parent_directory, "#{Time.now.to_i}-#{rand(99999999)}")
53
+ FileUtils.mkdir_p(current_directory) # make sure it's there
54
+ FileUtils.mv(current_directory, alt_directory)
55
+ read_directory(alt_directory)
56
+ end
57
+
58
+ def clear!
59
+ FileUtils.rm_rf(parent_directory)
60
+ end
61
+ end
62
+
63
+ class LogDevice # from Logger
64
+
65
+ attr_reader :dev
66
+ attr_reader :filename
67
+
68
+ class LogDeviceMutex
69
+ include MonitorMixin
70
+ end
71
+
72
+ def initialize(log = nil, opt = {})
73
+ @dev = @filename = nil
74
+ @mutex = LogDeviceMutex.new
75
+ if log.respond_to?(:write) and log.respond_to?(:close)
76
+ @dev = log
77
+ else
78
+ @dev = open_logfile(log)
79
+ @dev.sync = true
80
+ @filename = log
81
+ end
82
+ end
83
+
84
+ def write(message)
85
+ @mutex.synchronize do
86
+ @dev.write(message)
87
+ end
88
+ end
89
+
90
+ def close
91
+ begin
92
+ @mutex.synchronize do
93
+ @dev.close rescue nil
94
+ end
95
+ rescue Exception
96
+ @dev.close rescue nil
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def open_logfile(filename)
103
+ begin
104
+ open(filename, (File::WRONLY | File::APPEND))
105
+ rescue Errno::ENOENT
106
+ create_logfile(filename)
107
+ end
108
+ end
109
+
110
+ def create_logfile(filename)
111
+ begin
112
+ FileUtils.mkdir_p(File.dirname(filename))
113
+
114
+ logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT | File::EXCL))
115
+ logdev.flock(File::LOCK_EX)
116
+ logdev.sync = true
117
+ logdev.flock(File::LOCK_UN)
118
+ rescue Errno::EEXIST
119
+ # file is created by another process
120
+ logdev = open_logfile(filename)
121
+ logdev.sync = true
122
+ end
123
+ logdev
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,31 @@
1
+ module RouteCounter
2
+ class Middleware
3
+ attr_reader :env
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ @env = env
10
+ status, headers, body = @app.call(env)
11
+ write_result! if RouteCounter.config.enabled?
12
+ [status, headers, body]
13
+ end
14
+
15
+ def write_result!
16
+ result = env['action_dispatch.request.path_parameters']
17
+ return unless result
18
+
19
+ controller_name = result[:controller]
20
+ action_name = result[:action]
21
+
22
+ return unless controller_name && action_name
23
+
24
+ # TODO: case on config for types: file, redis, other
25
+ # TODO: use env['REQUEST_METHOD'] ?
26
+ RouteCounter::FileRecorder.action_visited(controller_name, action_name)
27
+ rescue Exception => e
28
+ RouteCounter.config.error!("[RouteCleaner] #{e.message}\n#{e.backtrace.join("\n")}")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ require 'fileutils'
2
+ require 'monitor'
3
+
4
+ # A recorder implements these class methods
5
+ # * action_visited(controller_name, action_name) : record that it was visited
6
+ # * actions_visited : returns hash of url => count
7
+ # * rotate! : backup what was recorded and start counting again. returns hash.
8
+ # * clear! : clear everything out
9
+
10
+ module RouteCounter
11
+ class RedisRecorder
12
+ class << self
13
+
14
+ def client
15
+ RouteCounter.config.redis
16
+ end
17
+
18
+ def current_key
19
+ "route_counter:current"
20
+ end
21
+
22
+ def read_key(key)
23
+ out = {}
24
+ client.hgetall(key).each do |action, num|
25
+ out[action] = num.to_i
26
+ end
27
+ out
28
+ end
29
+
30
+ def increment!(action_key, amount)
31
+ client.hincrby(current_key, action_key, amount)
32
+ end
33
+
34
+ def action_visited(controller_name, action_name)
35
+ key = "#{controller_name}##{action_name}"
36
+ increment!(key, 1)
37
+ end
38
+
39
+ def actions_visited
40
+ # returns what was visited and counts
41
+ read_key(current_key)
42
+ end
43
+
44
+ def rotate!
45
+ raise "not supported"
46
+ end
47
+
48
+ def clear!
49
+ client.del(current_key)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,13 @@
1
+ module RouteCounter
2
+ class Snapshot
3
+ class << self
4
+ # send to redis
5
+ def transfer!(recorder_klass)
6
+ hash = recorder_klass.rotate!
7
+ hash.each do |action, num|
8
+ RedisRecorder.increment!(action, num)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ namespace :routes do
2
+ namespace :count do
3
+ desc "Shows the routes and if they've been used locally"
4
+ task local: :environment do
5
+ RouteCounter::ConsoleFormatter.puts!(RouteCounter::FileRecorder)
6
+ end
7
+
8
+ desc "Shows the routes and if they've been used globally"
9
+ task global: :environment do
10
+ RouteCounter::ConsoleFormatter.puts!(RouteCounter::RedisRecorder)
11
+ end
12
+ end
13
+ end
14
+
15
+ namespace :route_counter do
16
+ desc "send local information to global"
17
+ task snapshot: :environment do
18
+ RouteCounter::Snapshot.transfer!(RouteCounter::FileRecorder)
19
+ end
20
+
21
+ namespace :local do
22
+ desc "clears out the local store"
23
+ task clear: :environment do
24
+ RouteCounter::FileRecorder.clear!
25
+ end
26
+ end
27
+
28
+ namespace :global do
29
+ desc "clears out the global store"
30
+ task clear: :environment do
31
+ RouteCounter::RedisRecorder.clear!
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module RouteCounter
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'route_counter/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "route_counter"
8
+ spec.version = RouteCounter::VERSION
9
+ spec.authors = ["Brian Leonard"]
10
+ spec.email = ["brian@bleonard.com"]
11
+ spec.summary = %q{Monitors the usage of your routes}
12
+ spec.description = %q{Helps you to find unused Rails routes}
13
+ spec.homepage = "https://github.com/taskrabbit/route_counter"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "rack"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "redis"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "byebug"
28
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe RouteCounter::Config do
4
+ it "should be returned from the module" do
5
+ RouteCounter.config.class.name.should == "RouteCounter::Config"
6
+ end
7
+
8
+ describe ".directory" do
9
+ it "should default to ~/" do
10
+ RouteCounter.send(:reset)
11
+ RouteCounter.config.directory.to_s.should == File.join(Dir.home, "route_counter")
12
+ end
13
+
14
+ it "should be defaulting to tmp directory in test" do
15
+ RouteCounter.config.directory.should =~ /\/tmp\/recorder/
16
+ end
17
+
18
+ it "should be able to be set" do
19
+ RouteCounter.config.directory = "something"
20
+ RouteCounter.config.directory.should == "something"
21
+ end
22
+ end
23
+
24
+ describe ".enabled" do
25
+ it "should defualt to false" do
26
+ RouteCounter.config.enabled.should == false
27
+ RouteCounter.config.enabled?.should == false
28
+ end
29
+
30
+ it "should be able to be set" do
31
+ RouteCounter.config.enabled = true
32
+
33
+ RouteCounter.config.enabled.should == true
34
+ RouteCounter.config.enabled?.should == true
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+
4
+ describe RouteCounter::FileRecorder do
5
+ before(:each) do
6
+ RouteCounter::FileRecorder.clear!
7
+ end
8
+
9
+ describe "#action_visited" do
10
+ it "should write to file" do
11
+ controller = "comments"
12
+ action_name = "create"
13
+
14
+ current_path = File.join(RouteCounter::FileRecorder.parent_directory, "current")
15
+ check_path = File.join(current_path, "comments", "create")
16
+
17
+ File.exists?(check_path).should == false
18
+
19
+ RouteCounter::FileRecorder.action_visited(controller, action_name)
20
+
21
+ File.exists?(check_path).should == true
22
+ File.read(check_path).should == 'X'
23
+
24
+ RouteCounter::FileRecorder.action_visited(controller, action_name)
25
+
26
+ File.read(check_path).should == 'XX'
27
+
28
+ paths = RouteCounter::FileRecorder.actions_visited
29
+ paths.should == { "comments#create" => 2 }
30
+
31
+ RouteCounter::FileRecorder.action_visited("engine/comments", "create")
32
+ paths = RouteCounter::FileRecorder.actions_visited
33
+ paths.should == { "comments#create" => 2, "engine/comments#create" => 1 }
34
+
35
+ File.exist?(current_path).should == true
36
+
37
+ paths = RouteCounter::FileRecorder.rotate!
38
+ paths.should == { "comments#create" => 2, "engine/comments#create" => 1 }
39
+
40
+ File.exist?(current_path).should == false
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe RouteCounter::RedisRecorder do
4
+ before(:each) do
5
+ @redis = RouteCounter.config.redis
6
+ RouteCounter::RedisRecorder.clear!
7
+ end
8
+
9
+ describe "#action_visited" do
10
+ it "should write to file" do
11
+ controller = "comments"
12
+ action_name = "create"
13
+
14
+ key = "route_counter:current"
15
+ action_key = "#{controller}##{action_name}"
16
+ @redis.exists(key).should == false
17
+
18
+ RouteCounter::RedisRecorder.action_visited(controller, action_name)
19
+
20
+ @redis.exists(key).should == true
21
+ @redis.hget(key, action_key).to_i.should == 1
22
+
23
+ RouteCounter::RedisRecorder.action_visited(controller, action_name)
24
+
25
+ @redis.hget(key, action_key).to_i.should == 2
26
+
27
+ paths = RouteCounter::RedisRecorder.actions_visited
28
+ paths.should == { "comments#create" => 2 }
29
+
30
+ RouteCounter::RedisRecorder.action_visited("engine/comments", "create")
31
+ paths = RouteCounter::RedisRecorder.actions_visited
32
+ paths.should == { "comments#create" => 2, "engine/comments#create" => 1 }
33
+
34
+ @redis.exists(key).should == true
35
+
36
+ RouteCounter::RedisRecorder.clear!
37
+
38
+ @redis.exists(key).should == false
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ require 'route_counter'
2
+
3
+ begin
4
+ require 'byebug'
5
+
6
+ module Kernel
7
+ alias :debugger :byebug
8
+ end
9
+
10
+ rescue LoadError => e
11
+ # byebug isn't installed - no debugging here!
12
+ end
13
+
14
+
15
+ RSpec.configure do |config|
16
+ config.mock_framework = :rspec
17
+
18
+ config.before(:each) do
19
+ RouteCounter.send(:reset)
20
+ RouteCounter.config.directory = File.expand_path("tmp/recorder")
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: route_counter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Leonard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: redis
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Helps you to find unused Rails routes
98
+ email:
99
+ - brian@bleonard.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .rspec
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - lib/route_counter.rb
111
+ - lib/route_counter/config.rb
112
+ - lib/route_counter/console_formatter.rb
113
+ - lib/route_counter/file_recorder.rb
114
+ - lib/route_counter/middleware.rb
115
+ - lib/route_counter/redis_recorder.rb
116
+ - lib/route_counter/snapshot.rb
117
+ - lib/route_counter/tasks.rb
118
+ - lib/route_counter/version.rb
119
+ - route_counter.gemspec
120
+ - spec/config_spec.rb
121
+ - spec/file_recorder_spec.rb
122
+ - spec/redis_recorder_spec.rb
123
+ - spec/spec_helper.rb
124
+ homepage: https://github.com/taskrabbit/route_counter
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 2.0.3
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Monitors the usage of your routes
148
+ test_files:
149
+ - spec/config_spec.rb
150
+ - spec/file_recorder_spec.rb
151
+ - spec/redis_recorder_spec.rb
152
+ - spec/spec_helper.rb
153
+ has_rdoc: