diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index ae395708cb..78d2471890 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -7,7 +7,7 @@ module Rails module Actions def initialize(*) # :nodoc: super - @in_group = nil + @indentation = 0 @after_bundle_callbacks = [] end @@ -36,13 +36,11 @@ module Rails log :gemfile, message - options.each do |option, value| - parts << "#{option}: #{quote(value)}" - end + parts << quote(options) unless options.empty? in_root do str = "gem #{parts.join(", ")}" - str = " " + str if @in_group + str = indentation + str str = "\n" + str append_file "Gemfile", str, verbose: false end @@ -54,20 +52,32 @@ module Rails # gem "rspec-rails" # end def gem_group(*names, &block) - name = names.map(&:inspect).join(", ") - log :gemfile, "group #{name}" + options = names.extract_options! + str = names.map(&:inspect) + str << quote(options) unless options.empty? + str = str.join(", ") + log :gemfile, "group #{str}" in_root do - append_file "Gemfile", "\ngroup #{name} do", force: true - - @in_group = true - instance_eval(&block) - @in_group = false - + append_file "Gemfile", "\ngroup #{str} do", force: true + with_indentation(&block) append_file "Gemfile", "\nend\n", force: true end end + def github(repo, options = {}, &block) + str = [quote(repo)] + str << quote(options) unless options.empty? + str = str.join(", ") + log :github, "github #{str}" + + in_root do + append_file "Gemfile", "\n#{indentation}github #{str} do", force: true + with_indentation(&block) + append_file "Gemfile", "\n#{indentation}end", force: true + end + end + # Add the given source to +Gemfile+ # # If block is given, gem entries in block are wrapped into the source group. @@ -83,9 +93,7 @@ module Rails in_root do if block append_file "Gemfile", "\nsource #{quote(source)} do", force: true - @in_group = true - instance_eval(&block) - @in_group = false + with_indentation(&block) append_file "Gemfile", "\nend\n", force: true else prepend_file "Gemfile", "source #{quote(source)}\n", verbose: false @@ -315,6 +323,11 @@ module Rails # Surround string with single quotes if there is no quotes. # Otherwise fall back to double quotes def quote(value) # :doc: + if value.respond_to? :each_pair + return value.map do |k, v| + "#{k}: #{quote(v)}" + end.join(", ") + end return value.inspect unless value.is_a? String if value.include?("'") @@ -334,6 +347,19 @@ module Rails "#{value.strip.indent(amount)}\n" end end + + # Indent the +Gemfile+ to the depth of @indentation + def indentation # :doc: + " " * @indentation + end + + # Manage +Gemfile+ indentation for a DSL action block + def with_indentation(&block) # :doc: + @indentation += 1 + instance_eval(&block) + ensure + @indentation -= 1 + end end end end diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index a54a6dbc28..da52b6076a 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -144,6 +144,44 @@ class ActionsTest < Rails::Generators::TestCase assert_file "Gemfile", /\ngroup :development, :test do\n gem 'rspec-rails'\nend\n\ngroup :test do\n gem 'fakeweb'\nend/ end + def test_github_should_create_an_indented_block + run_generator + + action :github, "user/repo" do + gem "foo" + gem "bar" + gem "baz" + end + + assert_file "Gemfile", /\ngithub 'user\/repo' do\n gem 'foo'\n gem 'bar'\n gem 'baz'\nend/ + end + + def test_github_should_create_an_indented_block_with_options + run_generator + + action :github, "user/repo", a: "correct", other: true do + gem "foo" + gem "bar" + gem "baz" + end + + assert_file "Gemfile", /\ngithub 'user\/repo', a: 'correct', other: true do\n gem 'foo'\n gem 'bar'\n gem 'baz'\nend/ + end + + def test_github_should_create_an_indented_block_within_a_group + run_generator + + action :gem_group, :magic do + github "user/repo", a: "correct", other: true do + gem "foo" + gem "bar" + gem "baz" + end + end + + assert_file "Gemfile", /\ngroup :magic do\n github 'user\/repo', a: 'correct', other: true do\n gem 'foo'\n gem 'bar'\n gem 'baz'\n end\nend\n/ + end + def test_environment_should_include_data_in_environment_initializer_block run_generator autoload_paths = 'config.autoload_paths += %w["#{Rails.root}/app/extras"]'