First step for upgrading to rails 3.
Check rake rails:upgrade:check for next steps.
This commit is contained in:
parent
a689bdd5f5
commit
4eba5fbc9c
45 changed files with 6139 additions and 2212 deletions
477
vendor/plugins/rails_upgrade/lib/application_checker.rb
vendored
Normal file
477
vendor/plugins/rails_upgrade/lib/application_checker.rb
vendored
Normal file
|
|
@ -0,0 +1,477 @@
|
|||
require 'open3'
|
||||
|
||||
module Rails
|
||||
module Upgrading
|
||||
class ApplicationChecker
|
||||
def initialize
|
||||
@issues = []
|
||||
|
||||
raise NotInRailsAppError unless in_rails_app?
|
||||
end
|
||||
|
||||
def in_rails_app?
|
||||
File.exist?("config/environment.rb")
|
||||
end
|
||||
|
||||
# Run all the check methods
|
||||
def run
|
||||
# Ruby 1.8 returns method names as strings whereas 1.9 uses symbols
|
||||
the_methods = (self.public_methods - Object.methods) - [:run, :initialize, "run", "initialize"]
|
||||
|
||||
the_methods.each {|m| send m }
|
||||
end
|
||||
|
||||
# Check for deprecated ActiveRecord calls
|
||||
def check_ar_methods
|
||||
files = []
|
||||
["find(:all", "find(:first", "find.*:conditions =>", ":joins =>"].each do |v|
|
||||
lines = grep_for(v, "app/")
|
||||
files += extract_filenames(lines) || []
|
||||
end
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Soon-to-be-deprecated ActiveRecord calls",
|
||||
"Methods such as find(:all), find(:first), finds with conditions, and the :joins option will soon be deprecated.",
|
||||
"http://m.onkey.org/2010/1/22/active-record-query-interface",
|
||||
files
|
||||
)
|
||||
end
|
||||
|
||||
lines = grep_for("named_scope", "app/models/")
|
||||
files = extract_filenames(lines)
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"named_scope is now just scope",
|
||||
"The named_scope method has been renamed to just scope.",
|
||||
"http://github.com/rails/rails/commit/d60bb0a9e4be2ac0a9de9a69041a4ddc2e0cc914",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def check_validation_on_methods
|
||||
files = []
|
||||
|
||||
["validate_on_create", "validate_on_update"].each do |v|
|
||||
lines = grep_for(v, "app/models/")
|
||||
files += extract_filenames(lines) || []
|
||||
end
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Updated syntax for validate_on_* methods",
|
||||
"Validate-on-callback methods (validate_on_create/validate_on_destroy) have been changed to validate :x, :on => :create",
|
||||
"https://rails.lighthouseapp.com/projects/8994/tickets/3880-validate_on_create-and-validate_on_update-no-longer-seem-to-exist",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def check_before_validation_on_methods
|
||||
files = []
|
||||
|
||||
%w(before_validation_on_create before_validation_on_update).each do |v|
|
||||
lines = grep_for(v, "app/models/")
|
||||
files += extract_filenames(lines) || []
|
||||
end
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Updated syntax for before_validation_on_* methods",
|
||||
"before_validation_on_* methods have been changed to before_validation(:on => :create/:update) { ... }",
|
||||
"https://rails.lighthouseapp.com/projects/8994/tickets/4699-before_validation_on_create-and-before_validation_on_update-doesnt-exist",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Check for deprecated router syntax
|
||||
def check_routes
|
||||
lines = ["map\\.", "ActionController::Routing::Routes", "\\.resources"].map do |v|
|
||||
grep_for(v, "config/routes.rb").empty? ? nil : true
|
||||
end.compact
|
||||
|
||||
unless lines.empty?
|
||||
alert(
|
||||
"Old router API",
|
||||
"The router API has totally changed.",
|
||||
"http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/",
|
||||
"config/routes.rb"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Check for deprecated test_help require
|
||||
def check_test_help
|
||||
files = []
|
||||
|
||||
# Hate to duplicate code, but we have to double quote this one...
|
||||
lines = grep_for("\'test_help\'", "test/", true)
|
||||
files += extract_filenames(lines) || []
|
||||
|
||||
lines = grep_for("\"test_help\"", "test/")
|
||||
files += extract_filenames(lines) || []
|
||||
|
||||
files.uniq!
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Deprecated test_help path",
|
||||
"You now must require 'rails/test_help' not just 'test_help'.",
|
||||
"http://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-practices",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Check for old (pre-application.rb) environment.rb file
|
||||
def check_environment
|
||||
unless File.exist?("config/application.rb")
|
||||
alert(
|
||||
"New file needed: config/application.rb",
|
||||
"You need to add a config/application.rb.",
|
||||
"http://omgbloglol.com/post/353978923/the-path-to-rails-3-approaching-the-upgrade",
|
||||
"config/application.rb"
|
||||
)
|
||||
end
|
||||
|
||||
lines = grep_for("config.", "config/environment.rb")
|
||||
|
||||
unless lines.empty?
|
||||
alert(
|
||||
"Old environment.rb",
|
||||
"environment.rb doesn't do what it used to; you'll need to move some of that into application.rb.",
|
||||
"http://omgbloglol.com/post/353978923/the-path-to-rails-3-approaching-the-upgrade",
|
||||
"config/environment.rb"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Check for deprecated constants
|
||||
def check_deprecated_constants
|
||||
files = []
|
||||
["RAILS_ENV", "RAILS_ROOT", "RAILS_DEFAULT_LOGGER"].each do |v|
|
||||
lines = grep_for(v, "app/")
|
||||
files += extract_filenames(lines) || []
|
||||
|
||||
lines = grep_for(v, "lib/")
|
||||
files += extract_filenames(lines) || []
|
||||
end
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Deprecated constant(s)",
|
||||
"Constants like RAILS_ENV, RAILS_ROOT, and RAILS_DEFAULT_LOGGER are now deprecated.",
|
||||
"http://litanyagainstfear.com/blog/2010/02/03/the-rails-module/",
|
||||
files.uniq
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Check for old-style config.gem calls
|
||||
def check_gems
|
||||
lines = grep_for("config.gem ", "config/*.rb")
|
||||
lines += grep_for("config.gem ", "config/**/*.rb")
|
||||
files = extract_filenames(lines)
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Old gem bundling (config.gems)",
|
||||
"The old way of bundling is gone now. You need a Gemfile for bundler.",
|
||||
"http://omgbloglol.com/post/353978923/the-path-to-rails-3-approaching-the-upgrade",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks for old mailer syntax in both mailer classes and those
|
||||
# classes utilizing the mailers
|
||||
def check_mailers
|
||||
lines = grep_for("deliver_", "app/models/ #{base_path}app/controllers/ #{base_path}app/observers/")
|
||||
files = extract_filenames(lines)
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Deprecated ActionMailer API",
|
||||
"You're using the old ActionMailer API to send e-mails in a controller, model, or observer.",
|
||||
"http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3",
|
||||
files
|
||||
)
|
||||
end
|
||||
|
||||
files = []
|
||||
["recipients ", "attachment(?!s) ", "(?<!:)subject ", "(?<!:)from "].each do |v|
|
||||
lines = grep_for_with_perl_regex(v, "app/models/")
|
||||
files += extract_filenames(lines) || []
|
||||
end
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Old ActionMailer class API",
|
||||
"You're using the old API in a mailer class.",
|
||||
"http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks for old-style generators
|
||||
def check_generators
|
||||
generators = Dir.glob(base_path + "vendor/plugins/**/generators/**/")
|
||||
|
||||
unless generators.empty?
|
||||
files = generators.reject do |g|
|
||||
grep_for("def manifest", g).empty?
|
||||
end.compact
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Old Rails generator API",
|
||||
"A plugin in the app is using the old generator API (a new one may be available at http://github.com/trydionel/rails3-generators).",
|
||||
"http://blog.plataformatec.com.br/2010/01/discovering-rails-3-generators/",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Checks a list of known broken plugins and gems
|
||||
def check_plugins
|
||||
# This list is off the wiki; will need to be updated often, esp. since RSpec is working on it
|
||||
bad_plugins = ["rspec", "rspec-rails", "hoptoad", "authlogic", "nifty-generators",
|
||||
"restful_authentication", "searchlogic", "cucumber", "cucumber-rails", "devise",
|
||||
"inherited_resources"]
|
||||
|
||||
bad_plugins = bad_plugins.map do |p|
|
||||
p if File.exist?("#{base_path}vendor/plugins/#{p}") || !Dir.glob("#{base_path}vendor/gems/#{p}-*").empty?
|
||||
end.compact
|
||||
|
||||
unless bad_plugins.empty?
|
||||
alert(
|
||||
"Known broken plugins",
|
||||
"At least one plugin in your app is broken (according to the wiki). Most of project maintainers are rapidly working towards compatability, but do be aware you may encounter issues.",
|
||||
"http://wiki.rubyonrails.org/rails/version3/plugins_and_gems",
|
||||
bad_plugins
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks for old-style ERb helpers
|
||||
def check_old_helpers
|
||||
|
||||
lines = grep_for("<% .*content_tag.* do.*%>", "app/views/**/*")
|
||||
lines += grep_for("<% .*javascript_tag.* do.*%>", "app/views/**/*")
|
||||
lines += grep_for("<% .*form_for.* do.*%>", "app/views/**/*")
|
||||
lines += grep_for("<% .*form_tag.* do.*%>", "app/views/**/*")
|
||||
lines += grep_for("<% .*fields_for.* do.*%>", "app/views/**/*")
|
||||
lines += grep_for("<% .*field_set_tag.* do.*%>", "app/views/**/*")
|
||||
|
||||
files = extract_filenames(lines)
|
||||
|
||||
if !files.blank?
|
||||
alert(
|
||||
"Deprecated ERb helper calls",
|
||||
"Block helpers that use concat (e.g., form_for) should use <%= instead of <%. The current form will continue to work for now, but you will get deprecation warnings since this form will go away in the future.",
|
||||
"http://weblog.rubyonrails.org/",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks for old-style AJAX helpers
|
||||
def check_old_ajax_helpers
|
||||
files = []
|
||||
['link_to_remote','form_remote_tag','remote_form_for'].each do |type|
|
||||
lines = grep_for(type, "app/views/**/*")
|
||||
inner_files = extract_filenames(lines)
|
||||
files += inner_files unless inner_files.nil?
|
||||
end
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Deprecated AJAX helper calls",
|
||||
"AJAX javascript helpers have been switched to be unobtrusive and use :remote => true instead of having a seperate function to handle remote requests.",
|
||||
"http://www.themodestrubyist.com/2010/02/24/rails-3-ujs-and-csrf-meta-tags/",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks for old cookie secret settings
|
||||
def check_old_cookie_secret
|
||||
lines = grep_for("ActionController::Base.cookie_verifier_secret = ", "config/**/*")
|
||||
files = extract_filenames(lines)
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Deprecated cookie secret setting",
|
||||
"Previously, cookie secret was set directly on ActionController::Base; it's now config.secret_token.",
|
||||
"http://lindsaar.net/2010/4/7/rails_3_session_secret_and_session_store",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def check_old_session_secret
|
||||
lines = grep_for("ActionController::Base.session = {", "config/**/*")
|
||||
files = extract_filenames(lines)
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Deprecated session secret setting",
|
||||
"Previously, session secret was set directly on ActionController::Base; it's now config.secret_token.",
|
||||
"http://lindsaar.net/2010/4/7/rails_3_session_secret_and_session_store",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks for old session settings
|
||||
def check_old_session_setting
|
||||
lines = grep_for("ActionController::Base.session_store", "config/**/*")
|
||||
files = extract_filenames(lines)
|
||||
|
||||
unless files.empty?
|
||||
alert(
|
||||
"Old session store setting",
|
||||
"Previously, session store was set directly on ActionController::Base; it's now config.session_store :whatever.",
|
||||
"http://lindsaar.net/2010/4/7/rails_3_session_secret_and_session_store",
|
||||
files
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def grep_for_with_perl_regex(text, where = "./", double_quote = false)
|
||||
grep_for(text, where, double_quote, true)
|
||||
end
|
||||
|
||||
# Find a string in a set of files; calls +find_with_grep+ and +find_with_rak+
|
||||
# depending on platform.
|
||||
#
|
||||
# TODO: Figure out if this works on Windows.
|
||||
def grep_for(text, where = "./", double_quote = false, perl_regex = false)
|
||||
# If they're on Windows, they probably don't have grep.
|
||||
@probably_has_grep ||= (Config::CONFIG['host_os'].downcase =~ /mswin|windows|mingw/).nil?
|
||||
|
||||
# protect against double root paths in Rails 3
|
||||
where.gsub!(Regexp.new(base_path),'')
|
||||
|
||||
lines = if @probably_has_grep
|
||||
find_with_grep(text, base_path + where, double_quote, perl_regex)
|
||||
else
|
||||
find_with_rak(text, base_path + where, double_quote)
|
||||
end
|
||||
|
||||
# ignore comments
|
||||
lines.gsub /^(\/[^:]+:)?\s*#.+$/m, ""
|
||||
end
|
||||
|
||||
# Sets a base path for finding files; mostly for testing
|
||||
def base_path
|
||||
Dir.pwd + "/"
|
||||
end
|
||||
|
||||
# Use the grep utility to find a string in a set of files
|
||||
def find_with_grep(text, where, double_quote, perl_regex = false)
|
||||
value = ""
|
||||
# Specifically double quote for finding 'test_help'
|
||||
command = if double_quote
|
||||
"grep -rH #{"-P" if perl_regex} \"#{text}\" #{where} | grep -v \.svn"
|
||||
else
|
||||
"grep -rH #{"-P" if perl_regex} '#{text}' #{where} | grep -v \.svn"
|
||||
end
|
||||
|
||||
Open3.popen3(command) do |stdin, stdout, stderr|
|
||||
value = stdout.read
|
||||
end
|
||||
value
|
||||
end
|
||||
|
||||
# Use the rak gem to grep the files (not yet implemented)
|
||||
def find_with_rak(text, where, double_quote)
|
||||
value = ""
|
||||
Open3.popen3("rak --nogroup -l '#{Regexp.escape(text)}' #{where}") do |stdin, stdout, stderr|
|
||||
value = stdout.read
|
||||
end
|
||||
value
|
||||
end
|
||||
|
||||
# Extract the filenames from the grep output
|
||||
def extract_filenames(output)
|
||||
if @probably_has_grep
|
||||
filenames = extract_filenames_from_grep(output)
|
||||
else
|
||||
filenames = extract_filenames_from_rak(output)
|
||||
end
|
||||
|
||||
filenames.compact.map do |f|
|
||||
f.gsub(base_path, "")
|
||||
end
|
||||
end
|
||||
|
||||
def extract_filenames_from_grep(output)
|
||||
return [] if output.empty?
|
||||
|
||||
output.split("\n").map do |fn|
|
||||
if m = fn.match(/^(.+?):/)
|
||||
m[1]
|
||||
end
|
||||
end.compact.uniq
|
||||
end
|
||||
|
||||
def extract_filenames_from_rak(output)
|
||||
return [] if output.empty?
|
||||
|
||||
output.split("\n").uniq
|
||||
end
|
||||
|
||||
# Terminal colors, borrowed from Thor
|
||||
CLEAR = "\e[0m"
|
||||
BOLD = "\e[1m"
|
||||
RED = "\e[31m"
|
||||
YELLOW = "\e[33m"
|
||||
CYAN = "\e[36m"
|
||||
WHITE = "\e[37m"
|
||||
|
||||
# Show an upgrade alert to the user
|
||||
def alert(title, text, more_info_url, culprits)
|
||||
if Config::CONFIG['host_os'].downcase =~ /mswin|windows|mingw/
|
||||
basic_alert(title, text, more_info_url, culprits)
|
||||
else
|
||||
color_alert(title, text, more_info_url, culprits)
|
||||
end
|
||||
end
|
||||
|
||||
# Show an upgrade alert to the user. If we're on Windows, we can't
|
||||
# use terminal colors, hence this method.
|
||||
def basic_alert(title, text, more_info_url, culprits)
|
||||
puts "** " + title
|
||||
puts text
|
||||
puts "More information: #{more_info_url}"
|
||||
puts
|
||||
puts "The culprits: "
|
||||
Array(culprits).each do |c|
|
||||
puts "\t- #{c}"
|
||||
end
|
||||
puts
|
||||
end
|
||||
|
||||
# Show a colorful alert to the user
|
||||
def color_alert(title, text, more_info_url, culprits)
|
||||
puts "#{RED}#{BOLD}#{title}#{CLEAR}"
|
||||
puts "#{WHITE}#{text}"
|
||||
puts "#{BOLD}More information:#{CLEAR} #{CYAN}#{more_info_url}"
|
||||
puts
|
||||
puts "#{WHITE}The culprits: "
|
||||
Array(culprits).each do |c|
|
||||
puts "#{YELLOW}\t- #{c}"
|
||||
end
|
||||
ensure
|
||||
puts "#{CLEAR}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
95
vendor/plugins/rails_upgrade/lib/gemfile_generator.rb
vendored
Normal file
95
vendor/plugins/rails_upgrade/lib/gemfile_generator.rb
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
module Rails
|
||||
module Upgrading
|
||||
class GemfileGenerator
|
||||
def generate_new_gemfile
|
||||
if has_environment?
|
||||
generate_gemfile
|
||||
else
|
||||
raise FileNotFoundError, "Can't find environment.rb [config/environment.rb]!"
|
||||
end
|
||||
end
|
||||
|
||||
def has_environment?
|
||||
File.exists?("config/environment.rb")
|
||||
end
|
||||
|
||||
def environment_code
|
||||
File.open("config/environment.rb").read
|
||||
end
|
||||
|
||||
def generate_gemfile
|
||||
environment_file = environment_code
|
||||
|
||||
# Get each line that starts with config.gem
|
||||
gem_lines = environment_file.split("\n").select {|l| l =~ /^\s*config\.gem/}
|
||||
|
||||
# Toss those lines to a generator class; the lines are evaluated in the
|
||||
# context of that instance.
|
||||
config = GemfileGenerator.new
|
||||
config.instance_eval(gem_lines.join("\n"))
|
||||
|
||||
config.output
|
||||
end
|
||||
end
|
||||
|
||||
class GemfileGenerator
|
||||
# Creates a target for the config.gem calls
|
||||
def config
|
||||
self
|
||||
end
|
||||
|
||||
def initialize
|
||||
@gems = []
|
||||
end
|
||||
|
||||
# Receive a call to add a gem to the list
|
||||
def gem(name, options={})
|
||||
data = {}
|
||||
|
||||
# Add new keys from old keys
|
||||
data[:require] = options[:lib] if options[:lib]
|
||||
data[:source] = options[:source] if options[:source]
|
||||
|
||||
version = options[:version]
|
||||
@gems << [name, version, data]
|
||||
end
|
||||
|
||||
# Generate the Gemfile output
|
||||
def output
|
||||
# Generic preamble, taken from Yehuda Katz's blog
|
||||
preamble = <<STR
|
||||
# Edit this Gemfile to bundle your application's dependencies.
|
||||
# This preamble is the current preamble for Rails 3 apps; edit as needed.
|
||||
source 'http://rubygems.org'
|
||||
|
||||
gem 'rails', '3.0.6'
|
||||
|
||||
STR
|
||||
preamble + generate_upgraded_code
|
||||
end
|
||||
|
||||
# Get Gemfile call for all the gems
|
||||
def generate_upgraded_code
|
||||
code = @gems.map do |name, version, data|
|
||||
version_string = (version ? "'#{version}'" : nil)
|
||||
source = data.delete(:source)
|
||||
|
||||
data_string = nil
|
||||
unless data.empty?
|
||||
data_string = data.to_a.map {|k, v| ":#{k} => '#{v}'"}.join(", ")
|
||||
end
|
||||
|
||||
# If we have a source, generate a call to +source+ then output the
|
||||
# gem call. Otherwise, just generate the gem requirement.
|
||||
if source
|
||||
str = ["'#{name}'", version_string, data_string].compact.join(", ")
|
||||
"source '#{source}'\ngem #{str}"
|
||||
else
|
||||
str = ["'#{name}'", version_string, data_string].compact.join(", ")
|
||||
"gem #{str}"
|
||||
end
|
||||
end.join("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
51
vendor/plugins/rails_upgrade/lib/new_configuration_generator.rb
vendored
Normal file
51
vendor/plugins/rails_upgrade/lib/new_configuration_generator.rb
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
module Rails
|
||||
module Upgrading
|
||||
class NewConfigurationGenerator
|
||||
def generate_new_configurations
|
||||
if has_environment?
|
||||
generate_new_application_rb
|
||||
else
|
||||
raise FileNotFoundError, "Can't find environment.rb [config/environment.rb]!"
|
||||
end
|
||||
end
|
||||
|
||||
def has_environment?
|
||||
File.exists?("config/environment.rb")
|
||||
end
|
||||
|
||||
def environment_code
|
||||
File.open("config/environment.rb").read
|
||||
end
|
||||
|
||||
def generate_new_application_rb
|
||||
environment_file = environment_code
|
||||
|
||||
initializer_code = ""
|
||||
if matches = environment_file.match(/Rails\:\:Initializer\.run do \|config\|\n(.*)\nend/m)
|
||||
initializer_code = matches[1]
|
||||
else
|
||||
raise "There doesn't seem to be a real environment.rb in your app. Are you sure config/environment.rb has the right contents?"
|
||||
end
|
||||
|
||||
frame = "# Put this in config/application.rb
|
||||
require File.expand_path('../boot', __FILE__)
|
||||
|
||||
module #{app_name.classify}
|
||||
class Application < Rails::Application
|
||||
%s
|
||||
end
|
||||
end"
|
||||
|
||||
frame % [indent(initializer_code)]
|
||||
end
|
||||
|
||||
def indent(text)
|
||||
text.split("\n").map {|l| " #{l}"}.join("\n")
|
||||
end
|
||||
|
||||
def app_name
|
||||
File.basename(Dir.pwd)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
0
vendor/plugins/rails_upgrade/lib/rails_upgrade.rb
vendored
Normal file
0
vendor/plugins/rails_upgrade/lib/rails_upgrade.rb
vendored
Normal file
366
vendor/plugins/rails_upgrade/lib/routes_upgrader.rb
vendored
Normal file
366
vendor/plugins/rails_upgrade/lib/routes_upgrader.rb
vendored
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
# TODO: Fix formatting on member/collection methods
|
||||
|
||||
module Rails
|
||||
module Upgrading
|
||||
module FakeRouter
|
||||
module ActionController
|
||||
module Routing
|
||||
class Routes
|
||||
def self.setup
|
||||
@redrawer = Rails::Upgrading::RouteRedrawer.new
|
||||
end
|
||||
|
||||
def self.redrawer
|
||||
@redrawer
|
||||
end
|
||||
|
||||
def self.draw
|
||||
yield @redrawer
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class RoutesUpgrader
|
||||
def generate_new_routes
|
||||
if has_routes_file?
|
||||
upgrade_routes
|
||||
else
|
||||
raise FileNotFoundError, "Can't find your routes file [config/routes.rb]!"
|
||||
end
|
||||
end
|
||||
|
||||
def has_routes_file?
|
||||
File.exists?("config/routes.rb")
|
||||
end
|
||||
|
||||
def routes_code
|
||||
File.read("config/routes.rb")
|
||||
end
|
||||
|
||||
def upgrade_routes
|
||||
FakeRouter::ActionController::Routing::Routes.setup
|
||||
|
||||
# Read and eval the file; our fake route mapper will capture
|
||||
# the calls to draw routes and generate new route code
|
||||
FakeRouter.module_eval(routes_code)
|
||||
|
||||
# Give the route set to the code generator and get its output
|
||||
generator = RouteGenerator.new(FakeRouter::ActionController::Routing::Routes.redrawer.routes)
|
||||
generator.generate
|
||||
end
|
||||
end
|
||||
|
||||
class RouteRedrawer
|
||||
attr_accessor :routes
|
||||
|
||||
def self.stack
|
||||
@stack
|
||||
end
|
||||
|
||||
def self.stack=(val)
|
||||
@stack = val
|
||||
end
|
||||
|
||||
def initialize
|
||||
@routes = []
|
||||
|
||||
# The old default route was actually two routes; we generate the new style
|
||||
# one only if we haven't generated it for the first old default route.
|
||||
@default_route_generated = false
|
||||
|
||||
# Setup the stack for parents; used use proper indentation
|
||||
self.class.stack = [@routes]
|
||||
end
|
||||
|
||||
def root(options)
|
||||
debug "mapping root"
|
||||
@routes << FakeRoute.new("/", options)
|
||||
end
|
||||
|
||||
def connect(path, options={})
|
||||
debug "connecting #{path}"
|
||||
|
||||
if (path == ":controller/:action/:id.:format" || path == ":controller/:action/:id")
|
||||
if !@default_route_generated
|
||||
current_parent << FakeRoute.new("/:controller(/:action(/:id))", {:default_route => true})
|
||||
|
||||
@default_route_generated = true
|
||||
end
|
||||
else
|
||||
current_parent << FakeRoute.new(path, options)
|
||||
end
|
||||
end
|
||||
|
||||
def resources(*args)
|
||||
if block_given?
|
||||
parent = FakeResourceRoute.new(args.shift)
|
||||
debug "mapping resources #{parent.name} with block"
|
||||
|
||||
parent = stack(parent) do
|
||||
yield(self)
|
||||
end
|
||||
|
||||
current_parent << parent
|
||||
else
|
||||
if args.last.is_a?(Hash)
|
||||
current_parent << FakeResourceRoute.new(args.shift, args.pop)
|
||||
debug "mapping resources #{current_parent.last.name} w/o block with args"
|
||||
else
|
||||
args.each do |a|
|
||||
current_parent << FakeResourceRoute.new(a)
|
||||
debug "mapping resources #{current_parent.last.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def resource(*args)
|
||||
if block_given?
|
||||
parent = FakeSingletonResourceRoute.new(args.shift)
|
||||
debug "mapping resource #{parent.name} with block"
|
||||
|
||||
parent = stack(parent) do
|
||||
yield(self)
|
||||
end
|
||||
|
||||
current_parent << parent
|
||||
else
|
||||
if args.last.is_a?(Hash)
|
||||
current_parent << FakeSingletonResourceRoute.new(args.shift, args.pop)
|
||||
debug "mapping resources #{current_parent.last.name} w/o block with args"
|
||||
else
|
||||
args.each do |a|
|
||||
current_parent << FakeSingletonResourceRoute.new(a)
|
||||
debug "mapping resources #{current_parent.last.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def namespace(name, options = {})
|
||||
debug "mapping namespace #{name}"
|
||||
namespace = FakeNamespace.new(name, options)
|
||||
|
||||
namespace = stack(namespace) do
|
||||
yield(self)
|
||||
end
|
||||
|
||||
current_parent << namespace
|
||||
end
|
||||
|
||||
def method_missing(m, *args)
|
||||
debug "named route: #{m}"
|
||||
current_parent << FakeRoute.new(args.shift, args.pop, m.to_s)
|
||||
end
|
||||
|
||||
def self.indent
|
||||
' ' * ((stack.length) * 2)
|
||||
end
|
||||
|
||||
private
|
||||
def debug(txt)
|
||||
puts txt if ENV['DEBUG']
|
||||
end
|
||||
|
||||
def stack(obj)
|
||||
self.class.stack << obj
|
||||
yield
|
||||
self.class.stack.pop
|
||||
end
|
||||
|
||||
def current_parent
|
||||
self.class.stack.last
|
||||
end
|
||||
end
|
||||
|
||||
class RouteObject
|
||||
def indent_lines(code_lines)
|
||||
if code_lines.length > 1
|
||||
code_lines.flatten.map {|l| "#{@indent}#{l.chomp}"}.join("\n") + "\n"
|
||||
else
|
||||
"#{@indent}#{code_lines.shift}"
|
||||
end
|
||||
end
|
||||
|
||||
def opts_to_string(opts)
|
||||
opts.is_a?(Hash) ? opts.map {|k, v|
|
||||
":#{k} => " + (v.is_a?(Hash) ? ('{ ' + opts_to_string(v) + ' }') : "#{value_to_string(v)}")
|
||||
}.join(", ") : opts.to_s
|
||||
end
|
||||
|
||||
def value_to_string(value)
|
||||
case value
|
||||
when Regexp then value.inspect
|
||||
when String then "'" + value.to_s + "'"
|
||||
else value.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class FakeNamespace < RouteObject
|
||||
attr_accessor :routes, :name, :options
|
||||
|
||||
def initialize(name, options = {})
|
||||
@routes = []
|
||||
@name, @options = name, options
|
||||
@indent = RouteRedrawer.indent
|
||||
end
|
||||
|
||||
def to_route_code
|
||||
if !@options.empty?
|
||||
options = ', ' + opts_to_string(@options)
|
||||
else
|
||||
options = ''
|
||||
end
|
||||
|
||||
lines = ["namespace :#{@name}#{options} do", @routes.map {|r| r.to_route_code}, "end"]
|
||||
|
||||
indent_lines(lines)
|
||||
end
|
||||
|
||||
def <<(val)
|
||||
@routes << val
|
||||
end
|
||||
|
||||
def last
|
||||
@routes.last
|
||||
end
|
||||
end
|
||||
|
||||
class FakeRoute < RouteObject
|
||||
attr_accessor :name, :path, :options
|
||||
|
||||
def initialize(path, options, name = "")
|
||||
@path = path
|
||||
@options = options || {}
|
||||
@name = name
|
||||
@indent = RouteRedrawer.indent
|
||||
end
|
||||
|
||||
def to_route_code
|
||||
if @options[:default_route]
|
||||
indent_lines ["match '#{@path}'"]
|
||||
else
|
||||
base = "match '%s' => '%s#%s'"
|
||||
extra_options = []
|
||||
|
||||
if not name.empty?
|
||||
extra_options << ":as => :#{name}"
|
||||
end
|
||||
|
||||
if @options[:requirements]
|
||||
@options[:constraints] = @options.delete(:requirements)
|
||||
end
|
||||
|
||||
if @options[:conditions]
|
||||
@options[:via] = @options.delete(:conditions).delete(:method)
|
||||
end
|
||||
|
||||
if @options[:method]
|
||||
@options[:via] = @options.delete(:method).to_s
|
||||
end
|
||||
|
||||
@options ||= {}
|
||||
base = (base % [@path, @options.delete(:controller), (@options.delete(:action) || "index")])
|
||||
opts = opts_to_string(@options)
|
||||
|
||||
route_pieces = ([base] + extra_options + [opts])
|
||||
route_pieces.delete("")
|
||||
|
||||
indent_lines [route_pieces.join(", ")]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class FakeResourceRoute < RouteObject
|
||||
attr_accessor :name, :children
|
||||
|
||||
def initialize(name, options = {})
|
||||
@name = name
|
||||
@children = []
|
||||
@options = options
|
||||
@indent = RouteRedrawer.indent
|
||||
end
|
||||
|
||||
def to_route_code
|
||||
# preserve :only & :except options
|
||||
copied_options = @options.reject { |k,v| ![:only, :except].member?(k) }
|
||||
unless copied_options.empty?
|
||||
copied_options_str = ", " + copied_options.map { |k, v| "#{k.inspect} => #{v.inspect}" }.join(",")
|
||||
end
|
||||
|
||||
if !@children.empty? || @options.has_key?(:collection) || @options.has_key?(:member)
|
||||
prefix = ["#{route_method} :#{@name}#{copied_options_str} do"]
|
||||
lines = prefix + custom_methods + [@children.map {|r| r.to_route_code}.join("\n"), "end"]
|
||||
|
||||
indent_lines(lines)
|
||||
else
|
||||
base = "#{route_method} :%s#{copied_options_str}"
|
||||
indent_lines [base % [@name]]
|
||||
end
|
||||
end
|
||||
|
||||
def custom_methods
|
||||
collection_code = generate_custom_methods_for(:collection)
|
||||
member_code = generate_custom_methods_for(:member)
|
||||
[collection_code, member_code]
|
||||
end
|
||||
|
||||
def generate_custom_methods_for(group)
|
||||
return "" unless @options[group]
|
||||
|
||||
method_code = []
|
||||
|
||||
RouteRedrawer.stack << self
|
||||
@options[group].each do |name, methods|
|
||||
[*methods].each do |method|
|
||||
method_code << "#{method} :#{name}"
|
||||
end
|
||||
end
|
||||
RouteRedrawer.stack.pop
|
||||
|
||||
indent_lines ["#{group} do", method_code, "end"].flatten
|
||||
end
|
||||
|
||||
def route_method
|
||||
"resources"
|
||||
end
|
||||
|
||||
def <<(val)
|
||||
@children << val
|
||||
end
|
||||
|
||||
def last
|
||||
@children.last
|
||||
end
|
||||
end
|
||||
|
||||
class FakeSingletonResourceRoute < FakeResourceRoute
|
||||
def route_method
|
||||
"resource"
|
||||
end
|
||||
end
|
||||
|
||||
class RouteGenerator
|
||||
def initialize(routes)
|
||||
@routes = routes
|
||||
@new_code = ""
|
||||
end
|
||||
|
||||
def generate
|
||||
@new_code = @routes.map do |r|
|
||||
r.to_route_code
|
||||
end.join("\n")
|
||||
|
||||
"#{app_name.underscore.classify}::Application.routes.draw do\n#{@new_code}\nend\n"
|
||||
end
|
||||
|
||||
private
|
||||
def app_name
|
||||
File.basename(Dir.pwd)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
78
vendor/plugins/rails_upgrade/lib/tasks/rails_upgrade_tasks.rake
vendored
Normal file
78
vendor/plugins/rails_upgrade/lib/tasks/rails_upgrade_tasks.rake
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
$:.unshift(File.dirname(__FILE__) + "/../../lib")
|
||||
require 'routes_upgrader'
|
||||
require 'gemfile_generator'
|
||||
require 'application_checker'
|
||||
require 'new_configuration_generator'
|
||||
|
||||
require 'fileutils'
|
||||
|
||||
namespace :rails do
|
||||
namespace :upgrade do
|
||||
desc "Runs a battery of checks on your Rails 2.x app and generates a report on required upgrades for Rails 3"
|
||||
task :check do
|
||||
checker = Rails::Upgrading::ApplicationChecker.new
|
||||
checker.run
|
||||
end
|
||||
|
||||
desc "Generates a Gemfile for your Rails 3 app out of your config.gem directives"
|
||||
task :gems do
|
||||
generator = Rails::Upgrading::GemfileGenerator.new
|
||||
new_gemfile = generator.generate_new_gemfile
|
||||
|
||||
puts new_gemfile
|
||||
end
|
||||
|
||||
desc "Create a new, upgraded route file from your current routes.rb"
|
||||
task :routes do
|
||||
upgrader = Rails::Upgrading::RoutesUpgrader.new
|
||||
new_routes = upgrader.generate_new_routes
|
||||
|
||||
puts new_routes
|
||||
end
|
||||
|
||||
desc "Extracts your configuration code so you can create a new config/application.rb"
|
||||
task :configuration do
|
||||
upgrader = Rails::Upgrading::NewConfigurationGenerator.new
|
||||
new_config = upgrader.generate_new_application_rb
|
||||
|
||||
puts new_config
|
||||
end
|
||||
|
||||
CLEAR = "\e[0m"
|
||||
CYAN = "\e[36m"
|
||||
WHITE = "\e[37m"
|
||||
|
||||
desc "Backs up your likely modified files so you can run the Rails 3 generator on your app with little risk"
|
||||
task :backup do
|
||||
files = [".gitignore",
|
||||
"app/controllers/application_controller.rb",
|
||||
"app/helpers/application_helper.rb",
|
||||
"config/routes.rb",
|
||||
"config/environment.rb",
|
||||
"config/environments/development.rb",
|
||||
"config/environments/production.rb",
|
||||
"config/environments/staging.rb",
|
||||
"config/database.yml",
|
||||
"config.ru",
|
||||
"doc/README_FOR_APP",
|
||||
"test/test_helper.rb"]
|
||||
|
||||
puts
|
||||
files.each do |f|
|
||||
if File.exist?(f)
|
||||
puts "#{CYAN}* #{CLEAR}backing up #{WHITE}#{f}#{CLEAR} to #{WHITE}#{f}.rails2#{CLEAR}"
|
||||
FileUtils.cp(f, "#{f}.rails2")
|
||||
end
|
||||
end
|
||||
|
||||
puts
|
||||
puts "This is a list of the files analyzed and backed up (if they existed);\nyou will probably not want the generator to replace them since\nyou probably modified them (but now they're safe if you accidentally do!)."
|
||||
puts
|
||||
|
||||
files.each do |f|
|
||||
puts "#{CYAN}- #{CLEAR}#{f}"
|
||||
end
|
||||
puts
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue