Created
October 5, 2009 02:23
-
-
Save 13k/201782 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# "grep"s through Rails views searching for a specific Route. | |
# | |
# You can think of it as a "which views links to this route" finder, | |
# good in refactoring scenarios. | |
# | |
# Actually the search is done using "ack" [http://betterthangrep.com], | |
# you must have it in your PATH. | |
# | |
# Also, this ack usage requires a definition of the Haml filetype for | |
# ack to understand the --haml commandline option. | |
# You can find this definition in this gist: http://gist.github.com/201795 | |
# and put in your ~/.ackrc file. | |
# | |
# The script searches for Routes in three ways: | |
# a. by searching named routes helpers usage | |
# b. by searching hand-crafted URLs | |
# c. by searching url_for's :controller and :action parameters | |
# | |
# It requires the Rails environment to recognize paths into Routes, | |
# so you must run it using Rails' script/runner launcher. | |
# | |
# Usage: ./script/runner what_links_to.rb [-z|--verbose] <URL> | |
# | |
# Example: ./script/runner what_links_to.rb '/posts/1/comments' -z | |
# | |
raise RuntimeError.new("You must run this script through Rails' script/runner launcher") \ | |
unless ENV['RAILS_ENV'] | |
require 'shellwords' | |
@verbose = ARGV.include?('--verbose') | |
@path = (ARGV.first == '--verbose') ? ARGV.second : ARGV.first | |
raise ArgumentError.new("You must provide an URL to look for") \ | |
if @path.nil? | |
@routes = ActionController::Routing::Routes.routes | |
@named_routes = ActionController::Routing::Routes.named_routes | |
def recognize(path) | |
@routes.find { |r| r.recognize(path, {:method => :get}) } | |
end | |
def named_route(route) | |
@named_routes.routes.index(route) | |
end | |
def ack(pattern) | |
`cd '#{RAILS_ROOT}' && ack --color --ruby --haml #{pattern.shellescape} app/views` | |
end | |
def ack_pipe(patterns) | |
first = ack(patterns.first) | |
second = "" | |
IO.popen("ack --color #{patterns.last.shellescape}", 'r+') do |f| | |
f.puts(first) | |
f.close_write | |
second = f.read | |
end | |
second | |
end | |
def path_pattern(route) | |
route.segments.inject("") do |str, s| | |
r = if s.instance_of? ActionController::Routing::DividerSegment or | |
s.instance_of? ActionController::Routing::StaticSegment | |
val = s.value.gsub('.', '\.') | |
s.is_optional ? "(#{val})?" : val | |
elsif s.instance_of? ActionController::Routing::DynamicSegment | |
# Can't use "s.regexp.source" cause there may be paths using interpolated Ruby code | |
'[^/.?]+' | |
elsif s.instance_of? ActionController::Routing::OptionalFormatSegment | |
'(\.\w+)?' | |
else | |
s.to_s.gsub('.', '\.') | |
end | |
str << r | |
end | |
end | |
def url_for_patterns(route) | |
patterns = route.requirements.map do |k,v| | |
[:controller, :action].include?(k) ? "#{k.inspect}\\s*=>\\s*[\"']#{v}[\"']" : nil | |
end.compact | |
patterns[0] = "(link_to|url_for).*#{patterns.first}" | |
patterns | |
end | |
def show(s) | |
s.strip! | |
print s.blank? ? "" : "#{s}\n" | |
end | |
route = recognize(@path) or raise RuntimeError.new("Could not find a route that matches #{@path}") | |
named = named_route(route) | |
named_patt = named.nil? ? "" : "\\b#{named}_(path|url)\\b" | |
patt = path_pattern(route) | |
url_for_patts = url_for_patterns(route) | |
puts route.to_s if @verbose | |
puts "named_route: #{named_patt.shellescape}" | |
puts "patt: #{patt.shellescape}" | |
puts "url_for: #{url_for_patts.first.shellescape}, #{url_for_patts.second.shellescape}" | |
unless named.nil? | |
show ack(named_patt) | |
end | |
unless patt.blank? | |
show ack(patt) | |
end | |
show ack_pipe(url_for_patts) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment