app_base.rb 4.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
require 'digest/md5'
require 'active_support/secure_random'
require 'rails/version' unless defined?(Rails::VERSION)
require 'rbconfig'
require 'open-uri'
require 'uri'

module Rails
  module Generators
    class AppBase < Base
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
      attr_accessor :rails_template
      add_shebang_option!

      argument :app_path,               :type => :string

      def self.add_shared_options_for(name)
        class_option :builder,            :type => :string, :aliases => "-b",
                                          :desc => "Path to a #{name} builder (can be a filesystem path or URL)"

        class_option :template,           :type => :string, :aliases => "-m",
                                          :desc => "Path to an #{name} template (can be a filesystem path or URL)"

        class_option :skip_gemfile,       :type => :boolean, :default => false,
                                          :desc => "Don't create a Gemfile"

        class_option :skip_git,           :type => :boolean, :aliases => "-G", :default => false,
                                          :desc => "Skip Git ignores and keeps"

        class_option :dev,                :type => :boolean, :default => false,
                                          :desc => "Setup the #{name} with Gemfile pointing to your Rails checkout"

        class_option :edge,               :type => :boolean, :default => false,
                                          :desc => "Setup the #{name} with Gemfile pointing to Rails repository"

        class_option :help,               :type => :boolean, :aliases => "-h", :group => :rails,
                                          :desc => "Show this help message and quit"
      end

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
      def initialize(*args)
        @original_wd = Dir.pwd

        super
      end

    protected

      def builder
        @builder ||= begin
          if path = options[:builder]
            if URI(path).is_a?(URI::HTTP)
              contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read }
            else
              contents = open(File.expand_path(path, @original_wd)) {|io| io.read }
            end

            prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1)
            instance_eval(&prok)
          end

          builder_class = get_builder_class
          builder_class.send(:include, ActionMethods)
          builder_class.new(self)
        end
      end

      def build(meth, *args)
        builder.send(meth, *args) if builder.respond_to?(meth)
      end

      def create_root
        self.destination_root = File.expand_path(app_path, destination_root)
        valid_const?

        empty_directory '.'
75
        set_default_accessors!
76 77
        FileUtils.cd(destination_root) unless options[:pretend]
      end
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

      def apply_rails_template
        apply rails_template if rails_template
      rescue Thor::Error, LoadError, Errno::ENOENT => e
        raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
      end

      def set_default_accessors!
        self.rails_template = case options[:template]
          when /^http:\/\//
            options[:template]
          when String
            File.expand_path(options[:template], Dir.pwd)
          else
            options[:template]
        end
      end
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128

      def rails_gemfile_entry
        if options.dev?
          <<-GEMFILE
gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}'
gem 'arel',  :git => 'git://github.com/rails/arel.git'
gem "rack", :git => "git://github.com/rack/rack.git"
          GEMFILE
        elsif options.edge?
          <<-GEMFILE
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'arel',  :git => 'git://github.com/rails/arel.git'
gem "rack", :git => "git://github.com/rack/rack.git"
          GEMFILE
        else
          <<-GEMFILE
gem 'rails', '#{Rails::VERSION::STRING}'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
# gem 'arel',  :git => 'git://github.com/rails/arel.git'
# gem "rack", :git => "git://github.com/rack/rack.git"
          GEMFILE
        end
      end

      def bundle_if_dev_or_edge
        bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
        run "#{bundle_command} install" if dev_or_edge?
      end

      def dev_or_edge?
        options.dev? || options.edge?
      end
129 130 131
    end
  end
end