Advanced Rails Creation Script

10 Feb 2007

Akhil Bansal recently wrote two excellent scripts for creating new Rails projects. The first was in bash (a sensible choice) and the second was a Ruby port of the same code. I’ve taken his code one step further and developed it into a Ruby program that’s easier to modify to your own needs.

Take the following code, throw it on your system somewhere and run it. It’ll set up a Rails app and take care of all the nutty details like ignoring log files and removing those pesky tmp and components directories from your repository.

    #!/usr/bin/env ruby
    require 'fileutils'

    class LayRails

      attr_accessor :path, :name, :svn_username, :svn_url, :svn_password

      def initialize
        setup && lay
      end

      def setup

        unless system('rails -v') || system('rails.cmd -v')
          puts "Cannot find rails. Terminating..."
          exit 0
        end    

        self.path = enter "Enter Rails Application Path:(eg: /home/akhil/ror): "
        self.name = ARGV.first || path.split('/').last
        self.svn_username = enter  "Enter svn username: "
        self.svn_password = enter "Enter the svn password: "
        self.svn_url = enter "Enter the svn url: "

        puts "
          ---------------------------------------
          Please verify the following variables: 
          Svn Username: #{svn_username}
          Svn URL: #{svn_url}
          Svn Password: #{svn_password.gsub(/./, '*')}
          Application Path: #{path}
          Application name: #{name}"

        while yes_no = enter("Proceed (y/n)").strip.upcase
          return true if 'Y' == yes_no
          if 'N' == yes_no
            puts 'Terminating...'
            exit 0
          else
            puts 'Please enter either a "y" or a "n"'
            puts 'yes_no: '+yes_no.inspect
          end
        end
      end

      def lay

        puts  "Generating rails project: (#{path})"
        @windows ?
          psystem("rails.cmd #{f path}") :
          psystem("rails #{f path}")

        puts  "SVNinitial import: "
        puts "svn import #{path} #{svn_url}/trunk -m \"Initial Import\" --username #{svn_username} --password #{svn_password.gsub(/./, '*')}"
        system "svn import #{path} #{svn_url}/trunk -m \"Initial Import\" --username #{svn_username} --password #{svn_password}"

        FileUtils.remove_dir(path, true)

        puts  "Checking out from svn: "

        psystem "svn checkout #{svn_url}/trunk #{path}"
        FileUtils.cd(path, :verbose => true)

        remove f('log/*'), 'Removing all log files from SVN'
        ignore '*', 'log', 'Ignoring all log files under log dir'
        remove 'tmp', 'Removing tmp directory from SVN'
        remove 'components', 'Removing components directory from SVN'
        ignore 'tmp', '.', 'Ignoring tmp dir'

        puts  "Generating optimized database file"
        File.open(f('config/database.yml'), 'w') {|f| f.write(database_yml_file) }
        puts  "Moving database.yml to database.example"
        psystem f('svn move config/database.yml config/database.example')
        psystem 'svn commit -m "Moving database.yml to database.example to provide a template for anyone who checks out the code " '
        ignore 'database.yml', 'config', 'Ignoring database.yml'
        puts  "Finished."
      end

      def remove(what, log)
        psystem "svn remove #{what}"
        commit log
      end

      def ignore(what, where, log)
        psystem "svn propset svn:ignore '#{what}' #{where}"
        psystem "svn update"
        commit log
      end

      def commit(log)
        psystem "svn commit -m '#{log}'"
      end

      def f(string)
        @windows ||= RUBY_PLATFORM =~ /mswin/i
        @windows ? 
          string.gsub('/', '\\') : 
          string
      end

      def psystem(string)
        puts string
        system string
      end

      def enter(string)
        puts string
        gets.strip
      end

      def database_yml_file
        <<DBYML
    credentials: &credentials
      adapter: mysql
      database: #{name}
      username: #{name}
      password: [add password]
      socket:  <%=
        ['/opt/local/var/run/mysql5/mysqld.sock', # darwinports
         '/opt/local/var/run/mysqld/mysqld.sock', # darwinports, again
         '/var/run/mysqld/mysqld.sock',           # ubuntu/debian/gentoo
         '/tmp/mysql.sock'].select { |f| File.exist? f }.first %>

    production:
      <<: *credentials
    development:
      <<: *credentials
      database: #{name}_development
    test:
      <<: *credentials
      database: #{name}_test
    DBYML
      end

      def credits
        puts <<CREDITS
    This script creates a new rails project and does the initial svn import with ignoring/deleting files from subversion
    Written by Danger <layrails@6brand.com> - based on the work of Akhil Bansal<bansalakhil30.10@gmail.com>"
    CREDITS
      end

    end

    # and away we go
    LayRails.new
    credentials: &credentials
      adapter: mysql
      database: #{name}
      username: #{name}
      password: [add password]
      socket:  <%=
        ['/opt/local/var/run/mysql5/mysqld.sock', # darwinports
         '/opt/local/var/run/mysqld/mysqld.sock', # darwinports, again
         '/var/run/mysqld/mysqld.sock',           # ubuntu/debian/gentoo
         '/tmp/mysql.sock'].select { |f| File.exist? f }.first %>

    production:
      <<: *credentials
    development:
      <<: *credentials
      database: #{name}_development
    test:
      <<: *credentials
      database: #{name}_test
    DBYML
      end

      def credits
        puts <<CREDITS
    This script creates a new rails project and does the initial svn import with ignoring/deleting files from subversion
    Written by Danger <layrails@6brand.com> - based on the work of Akhil Bansal<bansalakhil30.10@gmail.com>"
    CREDITS
      end

    end

    # and away we go
    LayRails.new

Please if you found this post helpful or have questions.