aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails/commands/commands_tasks.rb
blob: 43f9dd38f3c59372a08da8d48efdeac016e38cb3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
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
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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
129
130
131
132
133
134
135
136
require "rails/commands/rake_proxy"
require "rails/commands/common_commands_tasks"
require "active_support/core_ext/string/strip"

module Rails
  # This is a class which takes in a rails command and initiates the appropriate
  # initiation sequence.
  #
  # Warning: This class mutates ARGV because some commands require manipulating
  # it before they are run.
  class CommandsTasks # :nodoc:
    include Rails::RakeProxy
    include Rails::CommonCommandsTasks

    attr_reader :argv

    ADDITIONAL_COMMANDS = [
      [ "destroy", 'Undo code generated with "generate" (short-cut alias: "d")' ],
      [ "plugin new", "Generates skeleton for developing a Rails plugin" ],
      [ "runner",
        'Run a piece of code in the application environment (short-cut alias: "r")' ]
    ]

    def initialize(argv)
      @argv = argv
    end

    def plugin
      require_command!("plugin")
    end

    def console
      require_command!("console")
      options = Rails::Console.parse_arguments(argv)

      # RAILS_ENV needs to be set before config/application is required
      ENV["RAILS_ENV"] = options[:environment] if options[:environment]

      # shift ARGV so IRB doesn't freak
      shift_argv!

      require_application_and_environment!
      Rails::Console.start(Rails.application, options)
    end

    def server
      set_application_directory!
      require_command!("server")

      Rails::Server.new.tap do |server|
        # We need to require application after the server sets environment,
        # otherwise the --environment option given to the server won't propagate.
        require APP_PATH
        Dir.chdir(Rails.application.root)
        server.start
      end
    end

    def dbconsole
      require_command!("dbconsole")
      Rails::DBConsole.start
    end

    def runner
      require_command!("runner")
    end

    def new
      if %w(-h --help).include?(argv.first)
        require_command!("application")
      else
        exit_with_initialization_warning!
      end
    end

    private

      def exit_with_initialization_warning!
        puts "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.\n"
        puts "Type 'rails' for help."
        exit(1)
      end

      def shift_argv!
        argv.shift if argv.first && argv.first[0] != "-"
      end

      # Change to the application's path if there is no config.ru file in current directory.
      # This allows us to run `rails server` from other directories, but still get
      # the main config.ru and properly set the tmp directory.
      def set_application_directory!
        Dir.chdir(File.expand_path("../../", APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
      end

      def commands
        ADDITIONAL_COMMANDS + formatted_rake_tasks
      end

      def command_whitelist
        %w(plugin generate destroy console server dbconsole runner new version help test)
      end

      def help_message
        <<-EOT.strip_heredoc
          Usage: rails COMMAND [ARGS]

          The most common rails commands are:
           generate    Generate new code (short-cut alias: "g")
           console     Start the Rails console (short-cut alias: "c")
           server      Start the Rails server (short-cut alias: "s")
           test        Run tests (short-cut alias: "t")
           dbconsole   Start a console for the database specified in config/database.yml
                       (short-cut alias: "db")
           new         Create a new Rails application. "rails new my_app" creates a
                       new application called MyApp in "./my_app"

          All commands can be run with -h (or --help) for more information.

          In addition to those commands, there are:
        EOT
      end

      def require_application_and_environment!
        require APP_PATH
        Rails.application.require_environment!
      end

      def load_tasks
        Rails.application.load_tasks
      end

      def load_generators
        Rails.application.load_generators
      end
  end
end