Permalink
Browse files

Initial commit of Rake task/plugin version of rails-upgrade script

  • Loading branch information...
0 parents commit d6a740e2db57c710c662bf50425f4a5211b3dfc9 @jm committed Feb 1, 2010
@@ -0,0 +1,20 @@
+Copyright (c) 2010 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14 README
@@ -0,0 +1,14 @@
+= rails-upgrade
+
+A simple battery of scripts for upgrading Rails app/checking them for required updates. This application should work on Rails 2.x and 3.0, with a focus on upgrading to 3.0.
+
+== Usage
+
+ # Check your app for required upgrades
+ rake rails:upgrade:check
+
+ # Generate a new route file
+ rake rails:upgrade:routes
+
+ # Generate a Gemfile from your config.gem directives
+ rake rails:upgrade:gems
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the rails_upgrade plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the rails_upgrade plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'Rails-upgrade'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
@@ -0,0 +1 @@
+# Include hook code here
@@ -0,0 +1 @@
+# Install hook code here
@@ -0,0 +1,294 @@
+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
+ the_methods = (self.public_methods - Object.methods) - ["run", "initialize"]
+
+ the_methods.each {|m| send m }
+ end
+
+ # Check for deprecated ActiveRecord calls
+ def check_ar_methods
+ files = []
+ ["find(:all", "find(:first", ":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)
+
+ if files
+ 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
+
+ # 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 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 old-style config.gem calls
+ def check_gems
+ lines = grep_for("config.gem ", "config/*.rb")
+ files = extract_filenames(lines)
+
+ if files
+ 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)
+
+ if files
+ 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 ", "subject ", "from "].each do |v|
+ lines = grep_for(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.map do |g|
+ grep_for("def manifest", g).empty? ? g : nil
+ end.compact
+
+ if files
+ 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
+
+ private
+ # 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 = "./")
+ # If they're on Windows, they probably don't have grep.
+ @probably_has_grep ||= (Config::CONFIG['host_os'].downcase =~ /mswin|windows|mingw/).nil?
+
+ if @probably_has_grep
+ find_with_grep(text, base_path + where)
+ else
+ find_with_rak(text, base_path + where)
+ end
+ 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)
+ value = ""
+
+ Open3.popen3("grep -r '#{text}' #{where}") 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)
+ 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
+ extract_filenames_from_grep(output)
+ else
+ extract_filenames_from_rak(output)
+ end
+ end
+
+ def extract_filenames_from_grep(output)
+ return nil if output.empty?
+
+ # I hate rescue nil as much as the next guy but I have a reason here at least...
+ fnames = output.split("\n").map do |fn|
+ fn.match(/^(.+?):/)[1] rescue nil
+ end.compact
+
+ fnames.uniq
+ end
+
+ def extract_filenames_from_rak(output)
+ return nil 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: "
+ 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: "
+ culprits.each do |c|
+ puts "#{YELLOW}\t- #{c}"
+ end
+ ensure
+ puts "#{CLEAR}"
+ end
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit d6a740e

Please sign in to comment.