diff options
Diffstat (limited to 'railties/lib/rails/generators')
55 files changed, 369 insertions, 152 deletions
diff --git a/railties/lib/rails/generators/active_model.rb b/railties/lib/rails/generators/active_model.rb index e5373704d7..6183944bb0 100644 --- a/railties/lib/rails/generators/active_model.rb +++ b/railties/lib/rails/generators/active_model.rb @@ -1,5 +1,3 @@ -require 'active_support/deprecation' - module Rails module Generators # ActiveModel is a class to be implemented by each ORM to allow Rails to @@ -65,12 +63,6 @@ module Rails "#{name}.update(#{params})" end - def update_attributes(*args) # :nodoc: - ActiveSupport::Deprecation.warn("Calling '@orm_instance.update_attributes' " \ - "is deprecated, please use '@orm_instance.update' instead.") - update(*args) - end - # POST create # PATCH/PUT update def errors diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 675ada7ed0..3731be38ae 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -18,6 +18,10 @@ module Rails argument :app_path, type: :string + def self.strict_args_position + false + end + def self.add_shared_options_for(name) class_option :template, type: :string, aliases: '-m', desc: "Path to some #{name} template (can be a filesystem path or URL)" @@ -37,6 +41,9 @@ module Rails class_option :skip_active_record, type: :boolean, aliases: '-O', default: false, desc: 'Skip Active Record files' + class_option :skip_action_view, type: :boolean, aliases: '-V', default: false, + desc: 'Skip Action View files' + class_option :skip_sprockets, type: :boolean, aliases: '-S', default: false, desc: 'Skip Sprockets files' @@ -76,6 +83,17 @@ module Rails protected + def gemfile_entries + @gemfile_entries ||= [ + rails_gemfile_entry, + database_gemfile_entry, + assets_gemfile_entry, + javascript_gemfile_entry, + jbuilder_gemfile_entry, + webconsole_gemfile_entry, + sdoc_gemfile_entry].flatten + end + def builder @builder ||= begin builder_class = get_builder_class @@ -89,11 +107,10 @@ module Rails end def create_root - self.destination_root = File.expand_path(app_path, destination_root) + set_default_accessors! valid_const? empty_directory '.' - set_default_accessors! FileUtils.cd(destination_root) unless options[:pretend] end @@ -104,6 +121,7 @@ module Rails end def set_default_accessors! + self.destination_root = File.expand_path(app_path, destination_root) self.rails_template = case options[:template] when /^https?:\/\// options[:template] @@ -115,37 +133,52 @@ module Rails end def database_gemfile_entry - options[:skip_active_record] ? "" : - <<-GEMFILE.strip_heredoc - # Use #{options[:database]} as the database for Active Record - gem '#{gem_for_database}' - GEMFILE + return [] if options[:skip_active_record] + GemfileEntry.version gem_for_database, nil, + "Use #{options[:database]} as the database for Active Record" end def include_all_railties? - !options[:skip_active_record] && !options[:skip_test_unit] && !options[:skip_sprockets] + !options[:skip_active_record] && !options[:skip_action_view] && !options[:skip_test_unit] && !options[:skip_sprockets] end def comment_if(value) options[value] ? '# ' : '' end + class GemfileEntry < Struct.new(:name, :comment, :version, :options, :commented_out) + def initialize(name, comment, version, options = {}, commented_out = false) + super + end + + def self.github(name, github, comment = nil) + new(name, comment, nil, github: github) + end + + def self.version(name, version, comment = nil) + new(name, comment, version) + end + + def self.path(name, path, comment = nil) + new(name, comment, nil, path: path) + end + + def padding(max_width) + ' ' * (max_width - name.length + 2) + end + end + def rails_gemfile_entry if options.dev? - <<-GEMFILE.strip_heredoc - gem 'rails', path: '#{Rails::Generators::RAILS_DEV_PATH}' - gem 'arel', github: 'rails/arel' - GEMFILE + [GemfileEntry.path('rails', Rails::Generators::RAILS_DEV_PATH), + GemfileEntry.github('arel', 'rails/arel')] elsif options.edge? - <<-GEMFILE.strip_heredoc - gem 'rails', github: 'rails/rails' - gem 'arel', github: 'rails/arel' - GEMFILE + [GemfileEntry.github('rails', 'rails/rails'), + GemfileEntry.github('arel', 'rails/arel')] else - <<-GEMFILE.strip_heredoc - # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' - gem 'rails', '#{Rails::VERSION::STRING}' - GEMFILE + [GemfileEntry.version('rails', + Rails::VERSION::STRING, + "Bundle edge Rails instead: gem 'rails', github: 'rails/rails'")] end end @@ -177,77 +210,72 @@ module Rails end def assets_gemfile_entry - return if options[:skip_sprockets] + return [] if options[:skip_sprockets] - gemfile = if options.dev? || options.edge? - <<-GEMFILE.strip_heredoc - # Use edge version of sprockets-rails - gem 'sprockets-rails', github: 'rails/sprockets-rails' - - # Use SCSS for stylesheets - gem 'sass-rails', github: 'rails/sass-rails' - GEMFILE + gems = [] + if options.dev? || options.edge? + gems << GemfileEntry.github('sprockets-rails', 'rails/sprockets-rails', + 'Use edge version of sprockets-rails') + gems << GemfileEntry.github('sass-rails', 'rails/sass-rails', + 'Use SCSS for stylesheets') else - <<-GEMFILE.strip_heredoc - # Use SCSS for stylesheets - gem 'sass-rails', '~> 4.0.0.rc1' - GEMFILE + gems << GemfileEntry.version('sass-rails', + '~> 4.0.0.rc1', + 'Use SCSS for stylesheets') end - gemfile += <<-GEMFILE.strip_heredoc + gems << GemfileEntry.version('uglifier', + '>= 1.3.0', + 'Use Uglifier as compressor for JavaScript assets') - # Use Uglifier as compressor for JavaScript assets - gem 'uglifier', '>= 1.3.0' - GEMFILE + gems + end - if options[:skip_javascript] - gemfile += <<-GEMFILE - #{coffee_gemfile_entry} - #{javascript_runtime_gemfile_entry} - GEMFILE - end + def jbuilder_gemfile_entry + comment = 'Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder' + GemfileEntry.version('jbuilder', '~> 1.2', comment) + end + + def webconsole_gemfile_entry + comment = 'Run `rails console` in the browser. Read more: https://github.com/rails/web-console' + GemfileEntry.new('web-console', comment, nil, group: :development) + end - gemfile.gsub(/^[ \t]+/, '') + def sdoc_gemfile_entry + comment = 'bundle exec rake doc:rails generates the API under doc/api.' + GemfileEntry.new('sdoc', comment, nil, { :group => :doc, :require => false }) end def coffee_gemfile_entry + comment = 'Use CoffeeScript for .js.coffee assets and views' if options.dev? || options.edge? - <<-GEMFILE - # Use CoffeeScript for .js.coffee assets and views - gem 'coffee-rails', github: 'rails/coffee-rails' - GEMFILE + GemfileEntry.github 'coffee-rails', 'rails/coffee-rails', comment else - <<-GEMFILE - # Use CoffeeScript for .js.coffee assets and views - gem 'coffee-rails', '~> 4.0.0' - GEMFILE + GemfileEntry.version 'coffee-rails', '~> 4.0.0', comment end end def javascript_gemfile_entry - unless options[:skip_javascript] - <<-GEMFILE.gsub(/^[ \t]+/, '') - #{coffee_gemfile_entry} - #{javascript_runtime_gemfile_entry} - # Use #{options[:javascript]} as the JavaScript library - gem '#{options[:javascript]}-rails' - - # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks - gem 'turbolinks' - GEMFILE + if options[:skip_javascript] + [] + else + gems = [coffee_gemfile_entry, javascript_runtime_gemfile_entry] + gems << GemfileEntry.version("#{options[:javascript]}-rails", nil, + "Use #{options[:javascript]} as the JavaScript library") + + gems << GemfileEntry.version("turbolinks", nil, + "Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks") + gems end end def javascript_runtime_gemfile_entry - runtime = if defined?(JRUBY_VERSION) - "gem 'therubyrhino'" + comment = 'See https://github.com/sstephenson/execjs#readme for more supported runtimes' + if defined?(JRUBY_VERSION) + GemfileEntry.version 'therubyrhino', comment, nil else - "# gem 'therubyracer', platforms: :ruby" + GemfileEntry.new 'therubyracer', comment, nil, { :platforms => :ruby }, true end - <<-GEMFILE - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - #{runtime} - GEMFILE end def bundle_command(command) diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 7e938fab47..8aec8bc8f9 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -168,15 +168,15 @@ module Rails as_hook = options.delete(:as) || generator_name names.each do |name| - defaults = if options[:type] == :boolean - { } - elsif [true, false].include?(default_value_for_option(name, options)) - { banner: "" } - else - { desc: "#{name.to_s.humanize} to be invoked", banner: "NAME" } - end - unless class_options.key?(name) + defaults = if options[:type] == :boolean + { } + elsif [true, false].include?(default_value_for_option(name, options)) + { banner: "" } + else + { desc: "#{name.to_s.humanize} to be invoked", banner: "NAME" } + end + class_option(name, defaults.merge!(options)) end @@ -255,12 +255,7 @@ module Rails # Split the class from its module nesting nesting = class_name.split('::') last_name = nesting.pop - - # Extract the last Module in the nesting - last = nesting.inject(Object) do |last_module, nest| - break unless last_module.const_defined?(nest, false) - last_module.const_get(nest) - end + last = extract_last_module(nesting) if last && last.const_defined?(last_name.camelize, false) raise Error, "The name '#{class_name}' is either already used in your application " << @@ -270,6 +265,14 @@ module Rails end end + # Takes in an array of nested modules and extracts the last module + def extract_last_module(nesting) + nesting.inject(Object) do |last_module, nest| + break unless last_module.const_defined?(nest, false) + last_module.const_get(nest) + end + end + # Use Rails default banner. def self.banner "rails generate #{namespace.sub(/^rails:/,'')} #{self.arguments.map{ |a| a.usage }.join(' ')} [options]".gsub(/\s+/, ' ') diff --git a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb index 1799e823b6..69c10efa47 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb @@ -21,8 +21,13 @@ <%%= f.label :password_confirmation %><br> <%%= f.password_field :password_confirmation %> <% else -%> + <%- if attribute.reference? -%> + <%%= f.label :<%= attribute.column_name %> %><br> + <%%= f.<%= attribute.field_type %> :<%= attribute.column_name %> %> + <%- else -%> <%%= f.label :<%= attribute.name %> %><br> <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %> + <%- end -%> <% end -%> </div> <% end -%> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb index 9d778642f2..814d6fdb0e 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb @@ -6,9 +6,7 @@ <% attributes.reject(&:password_digest?).each do |attribute| -%> <th><%= attribute.human_name %></th> <% end -%> - <th></th> - <th></th> - <th></th> + <th colspan="3"></th> </tr> </thead> diff --git a/railties/lib/rails/generators/migration.rb b/railties/lib/rails/generators/migration.rb index cd69a017dd..3566f96f5e 100644 --- a/railties/lib/rails/generators/migration.rb +++ b/railties/lib/rails/generators/migration.rb @@ -1,15 +1,14 @@ +require 'active_support/concern' + module Rails module Generators # Holds common methods for migrations. It assumes that migrations has the # [0-9]*_name format and can be used by another frameworks (like Sequel) # just by implementing the next migration version method. module Migration + extend ActiveSupport::Concern attr_reader :migration_number, :migration_file_name, :migration_class_name - def self.included(base) #:nodoc: - base.extend ClassMethods - end - module ClassMethods def migration_lookup_at(dirname) #:nodoc: Dir.glob("#{dirname}/[0-9]*_*.rb") diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index d891ba1215..e712c747b0 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -18,6 +18,8 @@ module Rails parse_attributes! if respond_to?(:attributes) end + # Defines the template that would be used for the migration file. + # The arguments include the source template file, the migration filename etc. no_tasks do def template(source, *args, &block) inside_template do diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index d48dcf9ef3..6927cc52dd 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -68,7 +68,7 @@ module Rails directory "bin" do |content| "#{shebang}\n" + content end - chmod "bin", 0755, verbose: false + chmod "bin", 0755 & ~File.umask, verbose: false end def config @@ -129,7 +129,9 @@ module Rails end def vendor_javascripts - empty_directory_with_keep_file 'vendor/assets/javascripts' + unless options[:skip_javascript] + empty_directory_with_keep_file 'vendor/assets/javascripts' + end end def vendor_stylesheets @@ -151,23 +153,18 @@ module Rails desc: "Show Rails version number and quit" def initialize(*args) - if args[0].blank? - if args[1].blank? - # rails new - raise Error, "Application name should be provided in arguments. For details run: rails --help" - else - # rails new --skip-bundle my_new_application - raise Error, "Options should be given after the application name. For details run: rails --help" - end - end - super + unless app_path + raise Error, "Application name should be provided in arguments. For details run: rails --help" + end + if !options[:skip_active_record] && !DATABASES.include?(options[:database]) raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}." end end + public_task :set_default_accessors! public_task :create_root def create_root_files @@ -231,6 +228,12 @@ module Rails build(:leftovers) end + def delete_js_folder_skipping_javascript + if options[:skip_javascript] + remove_dir 'app/assets/javascripts' + end + end + public_task :apply_rails_template, :run_bundle protected @@ -245,7 +248,7 @@ module Rails end def app_name - @app_name ||= (defined_app_const_base? ? defined_app_name : File.basename(destination_root)).tr(".", "_") + @app_name ||= (defined_app_const_base? ? defined_app_name : File.basename(destination_root)).tr('\\', '').tr(". ", "_") end def defined_app_name @@ -300,5 +303,67 @@ module Rails defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder end end + + # This class handles preparation of the arguments before the AppGenerator is + # called. The class provides version or help information if they were + # requested, and also constructs the railsrc file (used for extra configuration + # options). + # + # This class should be called before the AppGenerator is required and started + # since it configures and mutates ARGV correctly. + class AppPreparer # :nodoc + attr_reader :argv + + def initialize(argv = ARGV) + @argv = argv + end + + def prepare! + handle_version_request!(argv.first) + unless handle_invalid_command!(argv.first) + argv.shift + handle_rails_rc! + end + end + + private + + def handle_version_request!(argument) + if ['--version', '-v'].include?(argv.first) + require 'rails/version' + puts "Rails #{Rails::VERSION::STRING}" + exit(0) + end + end + + def handle_invalid_command!(argument) + if argument != "new" + argv[0] = "--help" + end + end + + def handle_rails_rc! + unless argv.delete("--no-rc") + insert_railsrc_into_argv!(railsrc) + end + end + + def railsrc + if (customrc = argv.index{ |x| x.include?("--rc=") }) + File.expand_path(argv.delete_at(customrc).gsub(/--rc=/, "")) + else + File.join(File.expand_path("~"), '.railsrc') + end + end + + def insert_railsrc_into_argv!(railsrc) + if File.exist?(railsrc) + extra_args_string = File.read(railsrc) + extra_args = extra_args_string.split(/\n+/).map {|l| l.split}.flatten + puts "Using #{extra_args.join(" ")} from #{railsrc}" + argv.insert(1, *extra_args) + end + end + end end end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 577ff651e5..21dcba7947 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -1,28 +1,28 @@ source 'https://rubygems.org' -<%= rails_gemfile_entry -%> +<% max_width = gemfile_entries.map { |g| g.name.length }.max -%> +<% gemfile_entries.each do |gem| -%> +<% if gem.comment -%> -<%= database_gemfile_entry -%> - -<%= assets_gemfile_entry %> -<%= javascript_gemfile_entry -%> - -# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem 'jbuilder', '~> 1.2' - -group :doc do - # bundle exec rake doc:rails generates the API under doc/api. - gem 'sdoc', require: false -end +# <%= gem.comment %> +<% end -%> +<%= gem.commented_out ? '# ' : '' %>gem '<%= gem.name %>'<% if gem.version -%> +, '<%= gem.version %>' +<% elsif gem.options.any? -%> +,<%= gem.padding(max_width) %><%= gem.options.map { |k,v| + "#{k}: #{v.inspect}" }.join(', ') %> +<% else %> +<% end -%> +<% end -%> # Use ActiveModel has_secure_password -# gem 'bcrypt-ruby', '~> 3.0.0' +# gem 'bcrypt-ruby', '~> 3.1.2' # Use unicorn as the app server # gem 'unicorn' # Use Capistrano for deployment -# gem 'capistrano', group: :development +# gem 'capistrano-rails', group: :development <% unless defined?(JRUBY_VERSION) -%> # Use debugger diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt index 6899dfe9c9..8b91313e51 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt @@ -7,7 +7,8 @@ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // -// stub path allows dependency to be excluded from the asset bundle. +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. // <% unless options[:skip_javascript] -%> //= require <%= options[:javascript] %> diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css index 3192ec897b..a443db3401 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css @@ -5,9 +5,11 @@ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. * - * You're free to add application-wide styles to this file and they'll appear at the top of the - * compiled file, but it's generally better to create a new file per style scope. + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any styles + * defined in the other CSS/SCSS files in this directory. It is generally better to create a new + * file per style scope. * - *= require_self *= require_tree . + *= require_self */ diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt index d87c7b7268..4cf47bd0a0 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt @@ -2,8 +2,12 @@ <html> <head> <title><%= camelized %></title> + <%- if options[:skip_javascript] -%> + <%%= stylesheet_link_tag "application", media: "all" %> + <%- else -%> <%%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> <%%= javascript_include_tag "application", "data-turbolinks-track" => true %> + <%- end -%> <%%= csrf_meta_tags %> </head> <body> diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index ceb2bdf371..ac41a0cadb 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -4,9 +4,11 @@ require File.expand_path('../boot', __FILE__) require 'rails/all' <% else -%> # Pick the frameworks you want: +require "active_model/railtie" <%= comment_if :skip_active_record %>require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" +<%= comment_if :skip_action_view %>require "action_view/railtie" <%= comment_if :skip_sprockets %>require "sprockets/railtie" <%= comment_if :skip_test_unit %>require "rails/test_unit/railtie" <% end -%> diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml index eb569b7dab..0194dce6f3 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml @@ -55,6 +55,8 @@ production: adapter: postgresql encoding: unicode database: <%= app_name %>_production + # For details on connection pooling, see rails configration guide + # http://guides.rubyonrails.org/configuring.html#database-pooling pool: 5 username: <%= app_name %> password: diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index 91253d1508..cff570a631 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -20,7 +20,7 @@ Rails.application.configure do config.active_support.deprecation = :log <%- unless options.skip_active_record? -%> - # Raise an error on page load if there are pending migrations + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load <%- end -%> diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index 3dfb724164..3f66539d54 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -39,7 +39,7 @@ Rails.application.routes.draw do # get 'recent', on: :collection # end # end - + # Example resource route with concerns: # concern :toggleable do # post 'toggle' diff --git a/railties/lib/rails/generators/rails/controller/USAGE b/railties/lib/rails/generators/rails/controller/USAGE index 64239ad599..de33900e0a 100644 --- a/railties/lib/rails/generators/rails/controller/USAGE +++ b/railties/lib/rails/generators/rails/controller/USAGE @@ -16,3 +16,4 @@ Example: Test: test/controllers/credit_cards_controller_test.rb Views: app/views/credit_cards/debit.html.erb [...] Helper: app/helpers/credit_cards_helper.rb + Test: test/helpers/credit_cards_helper_test.rb diff --git a/railties/lib/rails/generators/rails/controller/controller_generator.rb b/railties/lib/rails/generators/rails/controller/controller_generator.rb index bae54623c6..ef84447df9 100644 --- a/railties/lib/rails/generators/rails/controller/controller_generator.rb +++ b/railties/lib/rails/generators/rails/controller/controller_generator.rb @@ -10,11 +10,45 @@ module Rails def add_routes actions.reverse.each do |action| - route %{get "#{file_name}/#{action}"} + route generate_routing_code(action) end end hook_for :template_engine, :test_framework, :helper, :assets + + private + + # This method creates nested route entry for namespaced resources. + # For eg. rails g controller foo/bar/baz index + # Will generate - + # namespace :foo do + # namespace :bar do + # get "baz/index" + # end + # end + def generate_routing_code(action) + depth = class_path.length + # Create 'namespace' ladder + # namespace :foo do + # namespace :bar do + namespace_ladder = class_path.each_with_index.map do |ns, i| + indent("namespace :#{ns} do\n", i * 2) + end.join + + # Create route + # get "baz/index" + route = indent(%{get "#{file_name}/#{action}"\n}, depth * 2) + + # Create `end` ladder + # end + # end + end_ladder = (1..depth).reverse_each.map do |i| + indent("end\n", i * 2) + end.join + + # Combine the 3 parts to generate complete route entry + namespace_ladder + route + end_ladder + end end end end diff --git a/railties/lib/rails/generators/rails/generator/USAGE b/railties/lib/rails/generators/rails/generator/USAGE index d28eb3d7d8..799383050c 100644 --- a/railties/lib/rails/generators/rails/generator/USAGE +++ b/railties/lib/rails/generators/rails/generator/USAGE @@ -10,3 +10,4 @@ Example: lib/generators/awesome/awesome_generator.rb lib/generators/awesome/USAGE lib/generators/awesome/templates/ + test/lib/generators/awesome_generator_test.rb diff --git a/railties/lib/rails/generators/rails/generator/generator_generator.rb b/railties/lib/rails/generators/rails/generator/generator_generator.rb index 9a7a516b5b..15d88f06ac 100644 --- a/railties/lib/rails/generators/rails/generator/generator_generator.rb +++ b/railties/lib/rails/generators/rails/generator/generator_generator.rb @@ -10,6 +10,8 @@ module Rails directory '.', generator_dir end + hook_for :test_framework + protected def generator_dir diff --git a/railties/lib/rails/generators/rails/model/USAGE b/railties/lib/rails/generators/rails/model/USAGE index 145d9ee6e0..833b7beb7f 100644 --- a/railties/lib/rails/generators/rails/model/USAGE +++ b/railties/lib/rails/generators/rails/model/USAGE @@ -60,7 +60,7 @@ Available field types: For decimal, two integers separated by a comma in curly braces will be used for precision and scale: - `rails generate model product price:decimal{10,2}` + `rails generate model product 'price:decimal{10,2}'` You can add a `:uniq` or `:index` suffix for unique or standard indexes respectively: diff --git a/railties/lib/rails/generators/rails/plugin_new/USAGE b/railties/lib/rails/generators/rails/plugin/USAGE index 9a7bf9f396..9a7bf9f396 100644 --- a/railties/lib/rails/generators/rails/plugin_new/USAGE +++ b/railties/lib/rails/generators/rails/plugin/USAGE diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index 850c9d5c0d..97ff6d1b8b 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -154,7 +154,7 @@ task default: :test end module Generators - class PluginNewGenerator < AppBase # :nodoc: + class PluginGenerator < AppBase # :nodoc: add_shared_options_for "plugin" alias_method :plugin_path, :app_path @@ -176,10 +176,12 @@ task default: :test "skip adding entry to Gemfile" def initialize(*args) - raise Error, "Options should be given after the plugin name. For details run: rails plugin new --help" if args[0].blank? - @dummy_path = nil super + + unless plugin_path + raise Error, "Plugin name should be provided in arguments. For details run: rails plugin new --help" + end end public_task :create_root diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec index 5fdf0e1554..5fdf0e1554 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec +++ b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin/templates/Gemfile index 3f2b78f2fd..d576784415 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin/templates/Gemfile @@ -23,7 +23,20 @@ end <% if options.dev? || options.edge? -%> # Your gem is dependent on dev or edge Rails. Once you can lock this # dependency down to a specific version, move it to your gemspec. -<%= rails_gemfile_entry -%> +<% max_width = gemfile_entries.map { |g| g.name.length }.max -%> +<% gemfile_entries.each do |gem| -%> +<% if gem.comment -%> + +# <%= gem.comment %> +<% end -%> +<%= gem.commented_out ? '# ' : '' %>gem '<%= gem.name %>'<% if gem.version -%> +, '<%= gem.version %>' +<% elsif gem.options.any? -%> +,<%= gem.padding(max_width) %><%= gem.options.map { |k,v| + "#{k}: #{v.inspect}" }.join(', ') %> +<% else %> +<% end -%> +<% end -%> <% end -%> # To use debugger diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE b/railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE index d7a9109894..d7a9109894 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE +++ b/railties/lib/rails/generators/rails/plugin/templates/MIT-LICENSE diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/README.rdoc b/railties/lib/rails/generators/rails/plugin/templates/README.rdoc index 301d647731..301d647731 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/README.rdoc +++ b/railties/lib/rails/generators/rails/plugin/templates/README.rdoc diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin/templates/Rakefile index 0ba899176c..0ba899176c 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin/templates/Rakefile diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%name%/application_controller.rb.tt index 448ad7f989..448ad7f989 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/app/controllers/%name%/application_controller.rb.tt diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/helpers/%name%/application_helper.rb.tt index 40ae9f52c2..40ae9f52c2 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/app/helpers/%name%/application_helper.rb.tt diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/mailers/.empty_directory b/railties/lib/rails/generators/rails/plugin/templates/app/mailers/.empty_directory index e69de29bb2..e69de29bb2 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/mailers/.empty_directory +++ b/railties/lib/rails/generators/rails/plugin/templates/app/mailers/.empty_directory diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory b/railties/lib/rails/generators/rails/plugin/templates/app/models/.empty_directory index e69de29bb2..e69de29bb2 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory +++ b/railties/lib/rails/generators/rails/plugin/templates/app/models/.empty_directory diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/views/layouts/%name%/application.html.erb.tt index 1d380420b4..1d380420b4 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/app/views/layouts/%name%/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/app/views/layouts/%name%/application.html.erb.tt diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt b/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt index c8de9f3e0f..c8de9f3e0f 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/config/routes.rb b/railties/lib/rails/generators/rails/plugin/templates/config/routes.rb index 8e158d5831..8e158d5831 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/config/routes.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/gitignore b/railties/lib/rails/generators/rails/plugin/templates/gitignore index 086d87818a..086d87818a 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/gitignore +++ b/railties/lib/rails/generators/rails/plugin/templates/gitignore diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%.rb index 40c074cced..40c074cced 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%/engine.rb index 967668fe66..967668fe66 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%/engine.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/version.rb b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%/version.rb index ef07ef2e19..ef07ef2e19 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/version.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/%name%/version.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake b/railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%name%_tasks.rake index 7121f5ae23..7121f5ae23 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake +++ b/railties/lib/rails/generators/rails/plugin/templates/lib/tasks/%name%_tasks.rake diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb index 310c975262..5508829f6b 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb @@ -7,6 +7,7 @@ require 'rails/all' <%= comment_if :skip_active_record %>require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" +<%= comment_if :skip_action_view %>require "action_view/railtie" <%= comment_if :skip_sprockets %>require "sprockets/railtie" <%= comment_if :skip_test_unit %>require "rails/test_unit/railtie" <% end -%> diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb index ef360470a3..ef360470a3 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/boot.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js index f84de00fd3..5bc2e1c8b5 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js @@ -7,6 +7,7 @@ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // -// stub path allows dependency to be excluded from the asset bundle. +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. // //= require_tree . diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb index 730ee31c3d..730ee31c3d 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/stylesheets.css b/railties/lib/rails/generators/rails/plugin/templates/rails/stylesheets.css index 3192ec897b..a443db3401 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/stylesheets.css +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/stylesheets.css @@ -5,9 +5,11 @@ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. * - * You're free to add application-wide styles to this file and they'll appear at the top of the - * compiled file, but it's generally better to create a new file per style scope. + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any styles + * defined in the other CSS/SCSS files in this directory. It is generally better to create a new + * file per style scope. * - *= require_self *= require_tree . + *= require_self */ diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb b/railties/lib/rails/generators/rails/plugin/templates/test/%name%_test.rb index 0a8bbd4aaf..0a8bbd4aaf 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/test/%name%_test.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb b/railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb index 824caecb24..824caecb24 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/test/integration/navigation_test.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb index 1e26a313cd..1e26a313cd 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb diff --git a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb index 4f36b612ae..6bf0a33a5f 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb @@ -13,7 +13,7 @@ module Rails argument :attributes, type: :array, default: [], banner: "field:type field:type" def create_controller_files - template "controller.rb", File.join('app/controllers', class_path, "#{controller_file_name}_controller.rb") + template "controller.rb", File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb") end hook_for :template_engine, :test_framework, as: :scaffold diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index 73e89086a5..0e69aa101f 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -59,9 +59,9 @@ class <%= controller_class_name %>Controller < ApplicationController # Only allow a trusted parameter "white list" through. def <%= "#{singular_table_name}_params" %> <%- if attributes_names.empty? -%> - params[<%= ":#{singular_table_name}" %>] + params[:<%= singular_table_name %>] <%- else -%> - params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>) + params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>) <%- end -%> end end diff --git a/railties/lib/rails/generators/resource_helpers.rb b/railties/lib/rails/generators/resource_helpers.rb index 7fd5c00768..a01eb57651 100644 --- a/railties/lib/rails/generators/resource_helpers.rb +++ b/railties/lib/rails/generators/resource_helpers.rb @@ -9,11 +9,19 @@ module Rails def self.included(base) #:nodoc: base.class_option :force_plural, type: :boolean, desc: "Forces the use of a plural ModelName" + base.class_option :model_name, type: :string, desc: "ModelName to be used" end # Set controller variables on initialization. def initialize(*args) #:nodoc: super + if options[:model_name] + controller_name = name + self.name = options[:model_name] + assign_names!(self.name) + else + controller_name = name + end if name == name.pluralize && name.singularize != name.pluralize && !options[:force_plural] unless ResourceHelpers.skip_warn @@ -24,19 +32,26 @@ module Rails assign_names!(name) end - @controller_name = name.pluralize + assign_controller_names!(controller_name.pluralize) end protected - attr_reader :controller_name + attr_reader :controller_name, :controller_file_name def controller_class_path - class_path + if options[:model_name] + @controller_class_path + else + class_path + end end - def controller_file_name - @controller_file_name ||= file_name.pluralize + def assign_controller_names!(name) + @controller_name = name + @controller_class_path = name.include?('/') ? name.split('/') : name.split('::') + @controller_class_path.map! { |m| m.underscore } + @controller_file_name = @controller_class_path.pop end def controller_file_path diff --git a/railties/lib/rails/generators/test_unit/generator/generator_generator.rb b/railties/lib/rails/generators/test_unit/generator/generator_generator.rb new file mode 100644 index 0000000000..d7307398ce --- /dev/null +++ b/railties/lib/rails/generators/test_unit/generator/generator_generator.rb @@ -0,0 +1,26 @@ +require 'rails/generators/test_unit' + +module TestUnit # :nodoc: + module Generators # :nodoc: + class GeneratorGenerator < Base # :nodoc: + check_class_collision suffix: "GeneratorTest" + + class_option :namespace, type: :boolean, default: true, + desc: "Namespace generator under lib/generators/name" + + def create_generator_files + template 'generator_test.rb', File.join('test/lib/generators', class_path, "#{file_name}_generator_test.rb") + end + + protected + + def generator_path + if options[:namespace] + File.join("generators", regular_class_path, file_name, "#{file_name}_generator") + else + File.join("generators", regular_class_path, "#{file_name}_generator") + end + end + end + end +end diff --git a/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb b/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb new file mode 100644 index 0000000000..a7f1fc4fba --- /dev/null +++ b/railties/lib/rails/generators/test_unit/generator/templates/generator_test.rb @@ -0,0 +1,16 @@ +require 'test_helper' +require '<%= generator_path %>' + +<% module_namespacing do -%> +class <%= class_name %>GeneratorTest < Rails::Generators::TestCase + tests <%= class_name %>Generator + destination Rails.root.join('tmp/generators') + setup :prepare_destination + + # test "generator runs without errors" do + # assert_nothing_raised do + # run_generator ["arguments"] + # end + # end +end +<% end -%> diff --git a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml index 90a92e6982..f19e9d1d87 100644 --- a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml +++ b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml @@ -1,4 +1,4 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html <% unless attributes.empty? -%> <% %w(one two).each do |name| %> <%= name %>: diff --git a/railties/lib/rails/generators/testing/assertions.rb b/railties/lib/rails/generators/testing/assertions.rb index 6267b2f2ee..cc88e830dd 100644 --- a/railties/lib/rails/generators/testing/assertions.rb +++ b/railties/lib/rails/generators/testing/assertions.rb @@ -21,7 +21,7 @@ module Rails # end # end def assert_file(relative, *contents) - absolute = File.expand_path(relative, destination_root) + absolute = File.expand_path(relative, destination_root).shellescape assert File.exists?(absolute), "Expected file #{relative.inspect} to exist, but does not" read = File.read(absolute) if block_given? || !contents.empty? |