diff options
25 files changed, 235 insertions, 96 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index e2a6ced1dc..ea1d090bc2 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,10 @@ +* Fix `ActionDispatch::ParamsParser#parse_formatted_parameters` to rewind body input stream on + parsing json params. + + Fixes #11345 + + *Yuri Bol*, *Paul Nikitochkin* + * Ignore spaces around delimiter in Set-Cookie header. *Yamagishi Kazutoshi* diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 4ca1d35489..b4cf8ad2f7 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -226,7 +226,7 @@ module ActionDispatch def raw_post unless @env.include? 'RAW_POST_DATA' raw_post_body = body - @env['RAW_POST_DATA'] = raw_post_body.read(@env['CONTENT_LENGTH'].to_i) + @env['RAW_POST_DATA'] = raw_post_body.read(content_length) raw_post_body.rewind if raw_post_body.respond_to?(:rewind) end @env['RAW_POST_DATA'] diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index fb70b60ef6..b426183488 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -41,7 +41,7 @@ module ActionDispatch when Proc strategy.call(request.raw_post) when :json - data = ActiveSupport::JSON.decode(request.body) + data = ActiveSupport::JSON.decode(request.raw_post) data = {:_json => data} unless data.is_a?(Hash) Request::Utils.deep_munge(data).with_indifferent_access else diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb index b62ed6a8b2..dba9ab688f 100644 --- a/actionpack/test/dispatch/request/json_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb @@ -70,6 +70,13 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest end end + test 'raw_post is not empty for JSON request' do + with_test_routing do + post '/parse', '{"posts": [{"title": "Post Title"}]}', 'CONTENT_TYPE' => 'application/json' + assert_equal '{"posts": [{"title": "Post Title"}]}', request.raw_post + end + end + private def assert_parses(expected, actual, headers = {}) with_test_routing do diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb index 147f9fd8ed..6fe250d3c1 100644 --- a/actionview/lib/action_view/helpers/text_helper.rb +++ b/actionview/lib/action_view/helpers/text_helper.rb @@ -254,7 +254,7 @@ module ActionView # # => "<p>Unblinkable.</p>" # # simple_format("<blink>Blinkable!</blink> It's true.", {}, sanitize: false) - # # => "<p><blink>Blinkable!</span> It's true.</p>" + # # => "<p><blink>Blinkable!</blink> It's true.</p>" def simple_format(text, html_options = {}, options = {}) wrapper_tag = options.fetch(:wrapper_tag, :p) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index c07fd67216..b3f97522c2 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -273,7 +273,7 @@ module ActiveRecord # person = Person.create!(name: 'David Heinemeier Hansson ' * 3) # # person.attribute_for_inspect(:name) - # # => "\"David Heinemeier Hansson David Heinemeier Hansson D...\"" + # # => "\"David Heinemeier Hansson David Heinemeier Hansson ...\"" # # person.attribute_for_inspect(:created_at) # # => "\"2012-10-22 00:15:07\"" @@ -281,7 +281,7 @@ module ActiveRecord value = read_attribute(attr_name) if value.is_a?(String) && value.length > 50 - "#{value[0..50]}...".inspect + "#{value[0..49]}...".inspect elsif value.is_a?(Date) || value.is_a?(Time) %("#{value.to_s(:db)}") else diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index cfff7202a3..75333765aa 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -307,8 +307,8 @@ module ActiveRecord # QUOTING ================================================== - # Returns a bind substitution value given a +column+ and list of current - # +binds+. + # Returns a bind substitution value given a bind +index+ and +column+ + # NOTE: The column param is currently being used by the sqlserver-adapter def substitute_at(column, index) Arel::Nodes::BindParam.new '?' end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 9186b33bd2..2d3bd563ac 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -238,7 +238,7 @@ module ActiveRecord raise RecordNotFound, error end - protected + private def find_with_associations join_dependency = construct_join_dependency @@ -246,7 +246,7 @@ module ActiveRecord if ActiveRecord::NullRelation === relation [] else - rows = connection.select_all(relation, 'SQL', relation.bind_values.dup) + rows = connection.select_all(relation.arel, 'SQL', relation.bind_values.dup) join_dependency.instantiate(rows) end end @@ -290,6 +290,12 @@ module ActiveRecord id_rows.map {|row| row[primary_key]} end + def using_limitable_reflections?(reflections) + reflections.none? { |r| r.collection? } + end + + protected + def find_with_ids(*ids) expects_array = ids.first.kind_of?(Array) return ids.first if expects_array && ids.first.empty? @@ -379,9 +385,5 @@ module ActiveRecord end end end - - def using_limitable_reflections?(reflections) - reflections.none? { |r| r.collection? } - end end end diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 0f9af8a0c3..c63f48e370 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -437,13 +437,6 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase assert george.treasures(true).empty? end - def test_deprecated_push_with_attributes_was_removed - jamis = developers(:jamis) - assert_raise(NoMethodError) do - jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today) - end - end - def test_associations_with_conditions assert_equal 3, projects(:active_record).developers.size assert_equal 1, projects(:active_record).developers_named_david.size diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index ee88fd490a..119e94b831 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -5,6 +5,7 @@ require 'models/reference' require 'models/job' require 'models/reader' require 'models/comment' +require 'models/rating' require 'models/tag' require 'models/tagging' require 'models/author' @@ -616,6 +617,11 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal post.author.author_favorites, post.author_favorites end + def test_merge_join_association_with_has_many_through_association_proxy + author = authors(:mary) + assert_nothing_raised { author.comments.ratings.to_sql } + end + def test_has_many_association_through_a_has_many_association_with_nonstandard_primary_keys assert_equal 2, owners(:blackbeard).toys.count end diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index ee0150558d..170c4cd9cd 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -32,7 +32,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters" assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on) - assert_equal '"The First Topic Now Has A Title With\nNewlines And M..."', t.attribute_for_inspect(:title) + assert_equal '"The First Topic Now Has A Title With\nNewlines And ..."', t.attribute_for_inspect(:title) end def test_attribute_present diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index af80b1ba42..feb828de31 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -13,7 +13,11 @@ class Author < ActiveRecord::Base has_many :posts_with_extension, :class_name => "Post" has_one :post_about_thinking, -> { where("posts.title like '%thinking%'") }, :class_name => 'Post' has_one :post_about_thinking_with_last_comment, -> { where("posts.title like '%thinking%'").includes(:last_comment) }, :class_name => 'Post' - has_many :comments, :through => :posts + has_many :comments, through: :posts do + def ratings + Rating.joins(:comment).merge(self) + end + end has_many :comments_containing_the_letter_e, :through => :posts, :source => :comments has_many :comments_with_order_and_conditions, -> { order('comments.body').where("comments.body like 'Thank%'") }, :through => :posts, :source => :comments has_many :comments_with_include, -> { includes(:post) }, :through => :posts, :source => :comments diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 221ceb532a..8b0b7c8d70 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,9 @@ +* Make `Time.at_with_coercion` retain the second fraction and return local time. + + Fixes #11350 + + *Neer Friedman*, *Andrew White* + * Make `HashWithIndifferentAccess#select` always return the hash, even when `Hash#select!` returns `nil`, to allow further chaining. diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index c539048a85..308a1b2cd9 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -408,7 +408,7 @@ module ActiveSupport options = merged_options(options) instrument(:exist?, name) do entry = read_entry(namespaced_key(name, options), options) - entry && !entry.expired? + (entry && !entry.expired?) || false end end diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index fa74fee78a..c739cce223 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -33,10 +33,15 @@ class Time # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime # instances can be used when called with a single argument def at_with_coercion(*args) - if args.size == 1 && args.first.acts_like?(:time) - at_without_coercion(args.first.to_i) + return at_without_coercion(*args) if args.size != 1 + + # Time.at can be called with a time or numerical value + time_or_number = args.first + + if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime) + at_without_coercion(time_or_number.to_f).getlocal else - at_without_coercion(*args) + at_without_coercion(time_or_number) end end alias_method :at_without_coercion, :at diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index ae6eaa4b60..d2382f0f5b 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -327,8 +327,8 @@ module CacheStoreBehavior def test_exist @cache.write('foo', 'bar') - assert @cache.exist?('foo') - assert !@cache.exist?('bar') + assert_equal true, @cache.exist?('foo') + assert_equal false, @cache.exist?('bar') end def test_nil_exist diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index d43cf41201..8741f033b5 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -700,6 +700,21 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end end + def test_at_with_datetime_returns_local_time + with_env_tz 'US/Eastern' do + dt = DateTime.civil(2000, 1, 1, 0, 0, 0, '+0') + assert_equal Time.local(1999, 12, 31, 19, 0, 0), Time.at(dt) + assert_equal 'EST', Time.at(dt).zone + assert_equal(-18000, Time.at(dt).utc_offset) + + # Daylight savings + dt = DateTime.civil(2000, 7, 1, 1, 0, 0, '+1') + assert_equal Time.local(2000, 6, 30, 20, 0, 0), Time.at(dt) + assert_equal 'EDT', Time.at(dt).zone + assert_equal(-14400, Time.at(dt).utc_offset) + end + end + def test_at_with_time_with_zone assert_equal Time.utc(2000, 1, 1, 0, 0, 0), Time.at(ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone['UTC'])) @@ -711,6 +726,45 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end end + def test_at_with_time_with_zone_returns_local_time + with_env_tz 'US/Eastern' do + twz = ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone['London']) + assert_equal Time.local(1999, 12, 31, 19, 0, 0), Time.at(twz) + assert_equal 'EST', Time.at(twz).zone + assert_equal(-18000, Time.at(twz).utc_offset) + + # Daylight savings + twz = ActiveSupport::TimeWithZone.new(Time.utc(2000, 7, 1, 0, 0, 0), ActiveSupport::TimeZone['London']) + assert_equal Time.local(2000, 6, 30, 20, 0, 0), Time.at(twz) + assert_equal 'EDT', Time.at(twz).zone + assert_equal(-14400, Time.at(twz).utc_offset) + end + end + + def test_at_with_time_microsecond_precision + assert_equal Time.at(Time.utc(2000, 1, 1, 0, 0, 0, 111)).to_f, Time.utc(2000, 1, 1, 0, 0, 0, 111).to_f + end + + def test_at_with_utc_time + with_env_tz 'US/Eastern' do + assert_equal Time.utc(2000), Time.at(Time.utc(2000)) + assert_equal 'UTC', Time.at(Time.utc(2000)).zone + assert_equal(0, Time.at(Time.utc(2000)).utc_offset) + end + end + + def test_at_with_local_time + with_env_tz 'US/Eastern' do + assert_equal Time.local(2000), Time.at(Time.local(2000)) + assert_equal 'EST', Time.at(Time.local(2000)).zone + assert_equal(-18000, Time.at(Time.local(2000)).utc_offset) + + assert_equal Time.local(2000, 7, 1), Time.at(Time.local(2000, 7, 1)) + assert_equal 'EDT', Time.at(Time.local(2000, 7, 1)).zone + assert_equal(-14400, Time.at(Time.local(2000, 7, 1)).utc_offset) + end + end + def test_eql? assert_equal true, Time.utc(2000).eql?( ActiveSupport::TimeWithZone.new(Time.utc(2000), ActiveSupport::TimeZone['UTC']) ) assert_equal true, Time.utc(2000).eql?( ActiveSupport::TimeWithZone.new(Time.utc(2000), ActiveSupport::TimeZone["Hawaii"]) ) diff --git a/guides/assets/javascripts/guides.js b/guides/assets/javascripts/guides.js index 7e494fb6d8..e4d25dfb21 100644 --- a/guides/assets/javascripts/guides.js +++ b/guides/assets/javascripts/guides.js @@ -1,57 +1,53 @@ -function guideMenu(){ - if (document.getElementById('guides').style.display == "none") { - document.getElementById('guides').style.display = "block"; - } else { - document.getElementById('guides').style.display = "none"; - } -} - -$.fn.selectGuide = function(guide){ +$.fn.selectGuide = function(guide) { $("select", this).val(guide); -} +}; -guidesIndex = { - bind: function(){ +var guidesIndex = { + bind: function() { var currentGuidePath = window.location.pathname; var currentGuide = currentGuidePath.substring(currentGuidePath.lastIndexOf("/")+1); $(".guides-index-small"). on("change", "select", guidesIndex.navigate). selectGuide(currentGuide); - $(".more-info-button:visible").click(function(e){ + $(document).on("click", ".more-info-button", function(e){ e.stopPropagation(); - if($(".more-info-links").is(":visible")){ + if ($(".more-info-links").is(":visible")) { $(".more-info-links").addClass("s-hidden").unwrap(); } else { $(".more-info-links").wrap("<div class='more-info-container'></div>").removeClass("s-hidden"); } - $(document).on("click", function(e){ - var $button = $(".more-info-button"); - var element; + }); + $("#guidesMenu").on("click", function(e) { + $("#guides").toggle(); + return false; + }); + $(document).on("click", function(e){ + e.stopPropagation(); + var $button = $(".more-info-button"); + var element; - // Cross browser find the element that had the event - if (e.target) element = e.target; - else if (e.srcElement) element = e.srcElement; + // Cross browser find the element that had the event + if (e.target) element = e.target; + else if (e.srcElement) element = e.srcElement; - // Defeat the older Safari bug: - // http://www.quirksmode.org/js/events_properties.html - if (element.nodeType == 3) element = element.parentNode; + // Defeat the older Safari bug: + // http://www.quirksmode.org/js/events_properties.html + if (element.nodeType === 3) element = element.parentNode; - var $element = $(element); + var $element = $(element); - var $container = $element.parents(".more-info-container"); + var $container = $element.parents(".more-info-container"); - // We've captured a click outside the popup - if($container.length == 0){ - $container = $button.next(".more-info-container"); - $container.find(".more-info-links").addClass("s-hidden").unwrap(); - $(document).off("click"); - } - }); + // We've captured a click outside the popup + if($container.length === 0){ + $container = $button.next(".more-info-container"); + $container.find(".more-info-links").addClass("s-hidden").unwrap(); + } }); }, navigate: function(e){ var $list = $(e.target); - url = $list.val(); + var url = $list.val(); window.location = url; } -} +}; diff --git a/guides/assets/stylesheets/main.css b/guides/assets/stylesheets/main.css index ca319c91cf..898f9ff05b 100644 --- a/guides/assets/stylesheets/main.css +++ b/guides/assets/stylesheets/main.css @@ -129,6 +129,7 @@ body { font-family: Helvetica, Arial, Sans-Serif; text-decoration: none; vertical-align: middle; + cursor: pointer; } .red-button:active { border-top: none; diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md index b9f42fa51b..24e16ecd40 100644 --- a/guides/source/contributing_to_ruby_on_rails.md +++ b/guides/source/contributing_to_ruby_on_rails.md @@ -234,8 +234,8 @@ workflow with the [rails-dev-box](https://github.com/rails/rails-dev-box). As a compromise, test what your code obviously affects, and if the change is not in railties run the whole test suite of the affected component. If all is -green that's enough to propose your contribution. We have [Travis CI](https -://travis-ci.org/) as a safety net for catching unexpected breakages +green that's enough to propose your contribution. We have [Travis CI](https://travis-ci.org/rails/rails) +as a safety net for catching unexpected breakages elsewhere. TIP: Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of Rails will generally not be accepted. diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb index c737a0e9dc..71d3c5638b 100644 --- a/guides/source/layout.html.erb +++ b/guides/source/layout.html.erb @@ -48,7 +48,7 @@ <ul class="nav"> <li><a class="nav-item" href="index.html">Home</a></li> <li class="guides-index guides-index-large"> - <a href="index.html" onclick="guideMenu(); return false;" id="guidesMenu" class="guides-index-item nav-item">Guides Index</a> + <a href="index.html" id="guidesMenu" class="guides-index-item nav-item">Guides Index</a> <div id="guides" class="clearfix" style="display: none;"> <hr /> <% ['L', 'R'].each do |position| %> @@ -143,7 +143,7 @@ <script type="text/javascript" src="javascripts/syntaxhighlighter/shBrushSql.js"></script> <script type="text/javascript" src="javascripts/syntaxhighlighter/shBrushPlain.js"></script> <script type="text/javascript"> - SyntaxHighlighter.all() + SyntaxHighlighter.all(); $(guidesIndex.bind); </script> </body> diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index 0f388d15c4..5992e94cd8 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -131,7 +131,15 @@ The following changes are meant for upgrading your application to Rails 4.0. ### Gemfile -Rails 4.0 removed the `assets` group from Gemfile. You'd need to remove that line from your Gemfile when upgrading. +Rails 4.0 removed the `assets` group from Gemfile. You'd need to remove that +line from your Gemfile when upgrading. You should also update your application +file (in `config/application.rb`): + +```ruby +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(:default, Rails.env) +``` ### vendor/plugins @@ -149,6 +157,9 @@ Rails 4.0 no longer supports loading plugins from `vendor/plugins`. You must rep * Rails 4.0 has removed `attr_accessible` and `attr_protected` feature in favor of Strong Parameters. You can use the [Protected Attributes gem](https://github.com/rails/protected_attributes) to a smoothly upgrade path. +* If you are not using Protected Attributes, you can remove any options related to +this gem such as `whitelist_attributes` or `mass_assignment_sanitizer` options. + * Rails 4.0 requires that scopes use a callable object such as a Proc or lambda: ```ruby @@ -208,6 +219,11 @@ Please read [Pull Request #9978](https://github.com/rails/rails/pull/9978) for d * Rails 4.0 deprecates the `dom_id` and `dom_class` methods in controllers (they are fine in views). You will need to include the `ActionView::RecordIdentifier` module in controllers requiring this feature. +* Rails 4.0 deprecates the `:confirm` option for the `link_to` helper. You should +instead rely on a data attribute (e.g. `data: { confirm: 'Are you sure?' }`). +This deprecation also concerns the helpers based on this one (such as `link_to_if` +or `link_to_unless`). + * Rails 4.0 changed how `assert_generates`, `assert_recognizes`, and `assert_routing` work. Now all these assertions raise `Assertion` instead of `ActionController::RoutingError`. * Rails 4.0 raises an `ArgumentError` if clashing named routes are defined. This can be triggered by explicitly defined named routes or by the `resources` method. Here are two examples that clash with routes named `example_path`: @@ -295,6 +311,12 @@ Active Record Observer and Action Controller Sweeper have been extracted to the ### sprockets-rails * `assets:precompile:primary` has been removed. Use `assets:precompile` instead. +* The `config.assets.compress` option should be changed to +`config.assets.js_compressor` like so for instance: + +```ruby +config.assets.js_compressor = :uglifier +``` ### sass-rails diff --git a/railties/lib/rails/commands/application.rb b/railties/lib/rails/commands/application.rb index 2ff29418c6..678697f09b 100644 --- a/railties/lib/rails/commands/application.rb +++ b/railties/lib/rails/commands/application.rb @@ -1,30 +1,3 @@ -require 'rails/version' - -if ['--version', '-v'].include?(ARGV.first) - puts "Rails #{Rails::VERSION::STRING}" - exit(0) -end - -if ARGV.first != "new" - ARGV[0] = "--help" -else - ARGV.shift - unless ARGV.delete("--no-rc") - customrc = ARGV.index{ |x| x.include?("--rc=") } - railsrc = if customrc - File.expand_path(ARGV.delete_at(customrc).gsub(/--rc=/, "")) - else - File.join(File.expand_path("~"), '.railsrc') - end - 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 - require 'rails/generators' require 'rails/generators/rails/app/app_generator' @@ -40,4 +13,5 @@ module Rails end end +Rails::Generators::AppPreparer.new(ARGV).prepare! Rails::Generators::AppGenerator.start diff --git a/railties/lib/rails/commands/commands_tasks.rb b/railties/lib/rails/commands/commands_tasks.rb index bb25d6419b..11524c4ef5 100644 --- a/railties/lib/rails/commands/commands_tasks.rb +++ b/railties/lib/rails/commands/commands_tasks.rb @@ -100,7 +100,7 @@ EOT end def version - ARGV.unshift '--version' + argv.unshift '--version' require_command!("application") end @@ -117,7 +117,7 @@ EOT end def shift_argv! - ARGV.shift if ARGV.first && ARGV.first[0] != '-' + argv.shift if argv.first && argv.first[0] != '-' end def require_command!(command) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index d48dcf9ef3..9fb8ea6955 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -300,5 +300,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(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(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 |