diff options
-rw-r--r-- | actionpack/CHANGELOG.md | 22 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/journey/path/pattern.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/mapper.rb | 28 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/route_set.rb | 2 | ||||
-rw-r--r-- | actionpack/test/dispatch/routing_test.rb | 58 | ||||
-rw-r--r-- | actionpack/test/journey/path/pattern_test.rb | 4 | ||||
-rw-r--r-- | activerecord/CHANGELOG.md | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/builder/belongs_to.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb | 11 | ||||
-rw-r--r-- | activerecord/test/cases/schema_dumper_test.rb | 12 | ||||
-rw-r--r-- | activerecord/test/cases/timestamp_test.rb | 12 | ||||
-rw-r--r-- | activerecord/test/schema/postgresql_specific_schema.rb | 6 | ||||
-rw-r--r-- | activesupport/CHANGELOG.md | 3 | ||||
-rw-r--r-- | activesupport/activesupport.gemspec | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/cache/file_store.rb | 4 | ||||
-rw-r--r-- | activesupport/test/caching_test.rb | 12 | ||||
-rw-r--r-- | guides/source/routing.md | 10 |
17 files changed, 170 insertions, 27 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 8ae23598b4..2a9afed35b 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,27 @@ ## Rails 4.0.0 (unreleased) ## +* Skip valid encoding checks for non-String parameters that come + from the matched route's defaults. + Fixes #9435. + + Example: + + root to: 'main#posts', page: 1 + + *Yves Senn* + +* Don't verify Regexp requirements for non-Regexp `:constraints`. + Fixes #9432. + + Example: + + get '/photos.:format' => 'feeds#photos', constraints: {format: 'xml'} + + *Yves Senn* + +* Make `ActionDispatch::Journey::Path::Pattern#new` raise more meaningful exception message. + + *Thierry Zires* ## Rails 4.0.0.beta1 (February 25, 2013) ## diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb index 4a571ec546..d37aa1fbe5 100644 --- a/actionpack/lib/action_dispatch/journey/path/pattern.rb +++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb @@ -20,7 +20,7 @@ module ActionDispatch @separators = strexp.separators.join @anchored = strexp.anchor else - raise "wtf bro: #{strexp}" + raise ArgumentError, "Bad expression: #{strexp}" end @names = nil diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 817480c7ae..dba9ccbfa5 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -124,15 +124,7 @@ module ActionDispatch def normalize_requirements! constraints.each do |key, requirement| next unless segment_keys.include?(key) || key == :controller - - if requirement.source =~ ANCHOR_CHARACTERS_REGEX - raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}" - end - - if requirement.multiline? - raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{requirement.inspect}" - end - + verify_regexp_requirement(requirement) if requirement.is_a?(Regexp) @requirements[key] = requirement end @@ -145,6 +137,16 @@ module ActionDispatch end end + def verify_regexp_requirement(requirement) + if requirement.source =~ ANCHOR_CHARACTERS_REGEX + raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}" + end + + if requirement.multiline? + raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{requirement.inspect}" + end + end + def normalize_defaults! @defaults.merge!(scope[:defaults]) if scope[:defaults] @defaults.merge!(options[:defaults]) if options[:defaults] @@ -425,11 +427,15 @@ module ActionDispatch # end # # [:constraints] - # Constrains parameters with a hash of regular expressions or an - # object that responds to <tt>matches?</tt> + # Constrains parameters with a hash of regular expressions + # or an object that responds to <tt>matches?</tt>. In addition, constraints + # other than path can also be specified with any object + # that responds to <tt>===</tt> (eg. String, Array, Range, etc.). # # match 'path/:id', constraints: { id: /[A-Z]\d{5}/ } # + # match 'json_only', constraints: { format: 'json' } + # # class Blacklist # def matches?(request) request.remote_ip == '1.2.3.4' end # end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index ff86f87d49..ca31b5e02e 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -31,6 +31,8 @@ module ActionDispatch # If any of the path parameters has a invalid encoding then # raise since it's likely to trigger errors further on. params.each do |key, value| + next unless value.respond_to?(:valid_encoding?) + unless value.valid_encoding? raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}" end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 37ad9ddb6b..4775324b43 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -1346,7 +1346,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'en', @request.params[:locale] end - def test_default_params + def test_default_string_params draw do get 'inline_pages/(:id)', :to => 'pages#show', :id => 'home' get 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' } @@ -1366,6 +1366,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'home', @request.params[:id] end + def test_default_integer_params + draw do + get 'inline_pages/(:page)', to: 'pages#show', page: 1 + get 'default_pages/(:page)', to: 'pages#show', defaults: { page: 1 } + + defaults page: 1 do + get 'scoped_pages/(:page)', to: 'pages#show' + end + end + + get '/inline_pages' + assert_equal 1, @request.params[:page] + + get '/default_pages' + assert_equal 1, @request.params[:page] + + get '/scoped_pages' + assert_equal 1, @request.params[:page] + end + def test_resource_constraints draw do resources :products, :constraints => { :id => /\d{4}/ } do @@ -3380,6 +3400,42 @@ class TestPortConstraints < ActionDispatch::IntegrationTest end end +class TestFormatConstraints < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + get '/string', to: ok, constraints: { format: 'json' } + get '/regexp', to: ok, constraints: { format: /json/ } + end + end + + include Routes.url_helpers + def app; Routes end + + def test_string_format_constraints + get 'http://www.example.com/string' + assert_response :success + + get 'http://www.example.com/string.json' + assert_response :success + + get 'http://www.example.com/string.html' + assert_response :not_found + end + + def test_regexp_format_constraints + get 'http://www.example.com/regexp' + assert_response :success + + get 'http://www.example.com/regexp.json' + assert_response :success + + get 'http://www.example.com/regexp.html' + assert_response :not_found + end +end + class TestRouteDefaults < ActionDispatch::IntegrationTest stub_controllers do |routes| Routes = routes diff --git a/actionpack/test/journey/path/pattern_test.rb b/actionpack/test/journey/path/pattern_test.rb index 2b7227cd0d..ce02104181 100644 --- a/actionpack/test/journey/path/pattern_test.rb +++ b/actionpack/test/journey/path/pattern_test.rb @@ -75,6 +75,10 @@ module ActionDispatch end end + def test_to_raise_exception_with_bad_expression + assert_raise(ArgumentError, "Bad expression: []") { Pattern.new [] } + end + def test_to_regexp_with_extended_group strexp = Router::Strexp.new( '/page/:name', diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 982fbdc236..44f3115add 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,10 @@ ## Rails 4.0.0 (unreleased) ## +* Do not try to touch invalid (and thus not persisted) parent record + for a `belongs_to :parent, touch: true` association + + *Olek Janiszewski* + * Fix when performing an ordered join query. The bug only affected queries where the order was given with a symbol. Fixes #9275. @@ -12,7 +17,7 @@ ## Rails 4.0.0.beta1 (February 25, 2013) ## -* Fix overriding of attributes by default_scope on `ActiveRecord::Base#dup`. +* Fix overriding of attributes by `default_scope` on `ActiveRecord::Base#dup`. *Hiroshige UMINO* diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index 2f2600b7fb..97b1ff18e2 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -48,7 +48,7 @@ module ActiveRecord::Associations::Builder def belongs_to_touch_after_save_or_destroy_for_#{name} record = #{name} - unless record.nil? + unless record.nil? || record.new_record? record.touch #{options[:touch].inspect if options[:touch] != true} end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb index cc289d4a14..f587bf8140 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb @@ -1,3 +1,5 @@ +require 'ipaddr' + module ActiveRecord module ConnectionAdapters # :nodoc: # The goal of this module is to move Adapter specific column @@ -50,6 +52,15 @@ module ActiveRecord when Range # infinity dumps as Infinity, which causes uninitialized constant error value.inspect.gsub('Infinity', '::Float::INFINITY') + when IPAddr + subnet_mask = value.instance_variable_get(:@mask_addr) + + # If the subnet mask is equal to /32, don't output it + if subnet_mask == (2**32 - 1) + "\"#{value.to_s}\"" + else + "\"#{value.to_s}/#{subnet_mask.to_s(2).count('1')}\"" + end else value.inspect end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index bfecc0d1e9..1147b9a09e 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -261,22 +261,22 @@ class SchemaDumperTest < ActiveRecord::TestCase def test_schema_dump_includes_inet_shorthand_definition output = standard_dump - if %r{create_table "postgresql_network_address"} =~ output - assert_match %r{t.inet "inet_address"}, output + if %r{create_table "postgresql_network_addresses"} =~ output + assert_match %r{t.inet\s+"inet_address",\s+default: "192.168.1.1"}, output end end def test_schema_dump_includes_cidr_shorthand_definition output = standard_dump - if %r{create_table "postgresql_network_address"} =~ output - assert_match %r{t.cidr "cidr_address"}, output + if %r{create_table "postgresql_network_addresses"} =~ output + assert_match %r{t.cidr\s+"cidr_address",\s+default: "192.168.1.0/24"}, output end end def test_schema_dump_includes_macaddr_shorthand_definition output = standard_dump - if %r{create_table "postgresql_network_address"} =~ output - assert_match %r{t.macaddr "macaddr_address"}, output + if %r{create_table "postgresql_network_addresses"} =~ output + assert_match %r{t.macaddr\s+"mac_address",\s+default: "ff:ff:ff:ff:ff:ff"}, output end end diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb index bb034848e1..777a2b70dd 100644 --- a/activerecord/test/cases/timestamp_test.rb +++ b/activerecord/test/cases/timestamp_test.rb @@ -113,6 +113,18 @@ class TimestampTest < ActiveRecord::TestCase assert_not_equal previously_owner_updated_at, pet.owner.updated_at end + def test_saving_a_new_record_belonging_to_invalid_parent_with_touch_should_not_raise_exception + klass = Class.new(Owner) do + def self.name; 'Owner'; end + validate { errors.add(:base, :invalid) } + end + + pet = Pet.new(owner: klass.new) + pet.save! + + assert pet.owner.new_record? + end + def test_saving_a_record_with_a_belongs_to_that_specifies_touching_a_specific_attribute_the_parent_should_update_that_attribute klass = Class.new(ActiveRecord::Base) do def self.name; 'Pet'; end diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb index 83b50030bd..d8271ac8d1 100644 --- a/activerecord/test/schema/postgresql_specific_schema.rb +++ b/activerecord/test/schema/postgresql_specific_schema.rb @@ -145,9 +145,9 @@ _SQL execute <<_SQL CREATE TABLE postgresql_network_addresses ( id SERIAL PRIMARY KEY, - cidr_address CIDR, - inet_address INET, - mac_address MACADDR + cidr_address CIDR default '192.168.1.0/24', + inet_address INET default '192.168.1.1', + mac_address MACADDR default 'ff:ff:ff:ff:ff:ff' ); _SQL diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index e76af6adc4..c47cb75274 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,8 @@ ## Rails 4.0.0 (unreleased) ## +* Fix deletion of empty directories in ActiveSupport::Cache::FileStore. + + *Charles Jones* ## Rails 4.0.0.beta1 (February 25, 2013) ## diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 819980eac9..c71525309b 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |s| s.rdoc_options.concat ['--encoding', 'UTF-8'] - s.add_dependency 'i18n', '~> 0.6.2' + s.add_dependency 'i18n', '~> 0.6', '>= 0.6.2' s.add_dependency 'multi_json', '~> 1.3' s.add_dependency 'tzinfo', '~> 0.3.33' s.add_dependency 'minitest', '~> 4.2' diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index 8e265ad863..0c55aa8a32 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -150,9 +150,9 @@ module ActiveSupport # Delete empty directories in the cache. def delete_empty_directories(dir) - return if dir == cache_path + return if File.realpath(dir) == File.realpath(cache_path) if Dir.entries(dir).reject {|f| EXCLUDED_DIRS.include?(f)}.empty? - File.delete(dir) rescue nil + Dir.delete(dir) rescue nil delete_empty_directories(File.dirname(dir)) end end diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 5158bbc196..ede08e23d5 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -672,6 +672,18 @@ class FileStoreTest < ActiveSupport::TestCase end end + def test_delete_does_not_delete_empty_parent_dir + sub_cache_dir = File.join(cache_dir, 'subdir/') + sub_cache_store = ActiveSupport::Cache::FileStore.new(sub_cache_dir) + assert_nothing_raised(Exception) do + assert sub_cache_store.write('foo', 'bar') + assert sub_cache_store.delete('foo') + end + assert File.exist?(cache_dir), "Parent of top level cache dir was deleted!" + assert File.exist?(sub_cache_dir), "Top level cache dir was deleted!" + assert Dir.entries(sub_cache_dir).reject {|f| ActiveSupport::Cache::FileStore::EXCLUDED_DIRS.include?(f)}.empty? + end + def test_log_exception_when_cache_read_fails File.expects(:exist?).raises(StandardError, "failed") @cache.send(:read_entry, "winston", {}) diff --git a/guides/source/routing.md b/guides/source/routing.md index 8c8ac34862..d7a4a237ed 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -797,6 +797,16 @@ You should put the `root` route at the top of the file, because it is the most p NOTE: The `root` route only routes `GET` requests to the action. +You can also use root inside namespaces and scopes as well. For example: + +```ruby +namespace :admin do + root to: "admin#index" +end + +root to: "home#index" +``` + ### Unicode character routes You can specify unicode character routes directly. For example: |