aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/generator.rb
blob: 28b41c60f04e7b6083a917dcaa2a7e9dbde6898b (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
require 'fileutils'
require 'active_record/support/inflector'

module Generator
  class GeneratorError < StandardError; end

  class Base
    @@template_root = File.dirname(__FILE__) + '/../generators/templates'
    cattr_accessor :template_root

    attr_reader :rails_root, :class_name, :file_name, :table_name,
                :actions, :options

    def initialize(rails_root, object_name, actions = [], options = {})
      @rails_root = rails_root
      @class_name = Inflector.camelize(object_name)
      @file_name  = Inflector.underscore(@class_name)
      @table_name = Inflector.pluralize(@file_name)
      @actions    = actions
      @options    = options

      # Use local templates if rails_root/generators directory exists.
      local_template_root = File.join(@rails_root, 'generators')
      if File.directory?(local_template_root)
        self.class.template_root = local_template_root
      end
    end

    protected

      # Generate a file in a fresh Rails app from an ERB template.
      # Takes a template path relative to +template_root+, a
      # destination path relative to +rails_root+, evaluates the template,
      # and writes the result to the destination.
      def generate_file(template_file_path, rails_file_path, eval_binding = nil)
        # Determine full paths for source and destination files.
        template_path = File.join(template_root, template_file_path)
        rails_path    = File.join(rails_root, rails_file_path)

        # Create destination directories.
        FileUtils.mkdir_p(File.dirname(rails_path))

        # Render template and write result.
        eval_binding ||= binding
        contents = ERB.new(File.read(template_path), nil, '-').result(eval_binding)
        File.open(rails_path, 'w') { |file| file.write(contents) }
      end
  end

  # Generate controller, helper, functional test, and views.
  class Controller < Base
    def generate
      options[:scaffold] = file_name if options[:scaffold]

      # Controller class.
      generate_file "controller.erb", "app/controllers/#{file_name}_controller.rb"

      # Helper class.
      generate_file "helper.erb", "app/helpers/#{file_name}_helper.rb"

      # Function test.
      generate_file "controller_test.erb", "test/functional/#{file_name}_controller_test.rb"

      # View template for each action.
      @actions.each do |action|
        generate_file "controller_view.rhtml",
                      "app/views/#{file_name}/#{action}.rhtml",
                      binding
      end
    end
  end

  # Generate model, unit test, and fixtures.
  class Model < Base
    def generate

      # Model class.
      generate_file "model.erb", "app/models/#{file_name}.rb"

      # Model unit test.
      generate_file "model_test.erb", "test/unit/#{file_name}_test.rb"

      # Test fixtures directory.
      FileUtils.mkdir_p("test/fixtures/#{table_name}")
    end
  end

  # Generate mailer, helper, functional test, and views.
  class Mailer < Base
    def generate

      # Mailer class.
      generate_file "mailer.erb", "app/models/#{file_name}.rb"

      # Mailer unit test.
      generate_file "mailer_test.erb", "test/unit/#{file_name}_test.rb"

      # Test fixtures directory.
      FileUtils.mkdir_p("test/fixtures/#{table_name}")

      # View template and fixture for each action.
      @actions.each do |action|
        generate_file "mailer_action.rhtml",
                      "app/views/#{file_name}/#{action}.rhtml",
                      binding
        generate_file "mailer_fixture.rhtml",
                      "test/fixtures/#{table_name}/#{action}",
                      binding
      end
    end
  end
end