diff options
18 files changed, 207 insertions, 129 deletions
diff --git a/actionpack/lib/abstract_controller/railties/routes_helpers.rb b/actionpack/lib/abstract_controller/railties/routes_helpers.rb index dec1e9d6d9..6684f46f64 100644 --- a/actionpack/lib/abstract_controller/railties/routes_helpers.rb +++ b/actionpack/lib/abstract_controller/railties/routes_helpers.rb @@ -5,8 +5,8 @@ module AbstractController Module.new do define_method(:inherited) do |klass| super(klass) - if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } - klass.send(:include, namespace._railtie.routes.url_helpers) + if namespace = klass.parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) } + klass.send(:include, namespace.railtie_routes_url_helpers) else klass.send(:include, routes.url_helpers) end diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb index 699c44c62c..bbe63149ad 100644 --- a/actionpack/lib/action_controller/railties/paths.rb +++ b/actionpack/lib/action_controller/railties/paths.rb @@ -6,13 +6,14 @@ module ActionController define_method(:inherited) do |klass| super(klass) - if namespace = klass.parents.detect {|m| m.respond_to?(:_railtie) } - paths = namespace._railtie.paths["app/helpers"].existent + if namespace = klass.parents.detect { |m| m.respond_to?(:railtie_helpers_paths) } + paths = namespace.railtie_helpers_paths else - paths = app.config.helpers_paths + paths = app.helpers_paths end klass.helpers_path = paths + if klass.superclass == ActionController::Base && ActionController::Base.include_all_helpers klass.helper :all end diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index d4208ca96e..84e3dd16dd 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -54,12 +54,7 @@ module ActionDispatch rescue Exception => e # YAML, XML or Ruby code block errors logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}" - raise - { "body" => request.raw_post, - "content_type" => request.content_mime_type, - "content_length" => request.content_length, - "exception" => "#{e.message} (#{e.class})", - "backtrace" => e.backtrace } + raise e end def content_type_from_legacy_post_data_format_header(env) diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index 20d11377f6..fc829aa6b4 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -34,10 +34,8 @@ module Blog set_table_name 'projects' end - def self._railtie - o = Object.new - def o.railtie_name; "blog" end - o + def self.use_relative_model_naming? + true end end diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb index 39245e9574..74067cb895 100644 --- a/actionpack/test/controller/show_exceptions_test.rb +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -22,7 +22,7 @@ module ShowExceptions ['127.0.0.1', '127.0.0.127', '::1', '0:0:0:0:0:0:0:1', '0:0:0:0:0:0:0:1%0'].each do |ip_address| self.remote_addr = ip_address get '/' - assert_match /boom/, body + assert_match(/boom/, body) end end @@ -31,7 +31,7 @@ module ShowExceptions @app = ShowExceptionsController.action(:boom) self.remote_addr = '208.77.188.166' get '/' - assert_match /boom/, body + assert_match(/boom/, body) end end @@ -53,7 +53,7 @@ module ShowExceptions test 'show diagnostics message' do @app = ShowExceptionsOverridenController.action(:boom) get '/', {'detailed' => '1'} - assert_match /boom/, body + assert_match(/boom/, body) end end end diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb index d854d55173..d481a2df13 100644 --- a/actionpack/test/dispatch/request/json_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb @@ -45,6 +45,18 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest end end + test "occurring a parse error if parsing unsuccessful" do + with_test_routing do + begin + $stderr = StringIO.new # suppress the log + json = "[\"person]\": {\"name\": \"David\"}}" + assert_raise(MultiJson::DecodeError) { post "/parse", json, {'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => false} } + ensure + $stderr = STDERR + end + end + end + private def assert_parses(expected, actual, headers = {}) with_test_routing do diff --git a/actionpack/test/dispatch/request/xml_params_parsing_test.rb b/actionpack/test/dispatch/request/xml_params_parsing_test.rb index 38453dfe48..65a25557b7 100644 --- a/actionpack/test/dispatch/request/xml_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/xml_params_parsing_test.rb @@ -67,6 +67,18 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest end end + test "occurring a parse error if parsing unsuccessful" do + with_test_routing do + begin + $stderr = StringIO.new # suppress the log + xml = "<person><name>David</name></pineapple>" + assert_raise(REXML::ParseException) { post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => false) } + ensure + $stderr = STDERR + end + end + end + test "parses multiple files" do xml = <<-end_body <person> diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index 363403092b..f2362714d7 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -175,8 +175,8 @@ class HashBackedAuthor < Hash end module Blog - def self._railtie - self + def self.use_relative_model_naming? + true end class Post < Struct.new(:title, :id) diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 34486bb151..ccedcd7dac 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -740,7 +740,7 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end - def test_form_for_with_isolated_namespaced_model + def test_form_for_with_model_using_relative_model_naming form_for(@blog_post) do |f| concat f.text_field :title concat f.submit('Edit post') diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index f16459ede2..2566920d63 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -13,18 +13,18 @@ module ActiveModel def initialize(klass, namespace = nil, name = nil) name ||= klass.name super(name) - @unnamespaced = self.sub(/^#{namespace.name}::/, '') if namespace - @klass = klass - @singular = _singularize(self).freeze - @plural = ActiveSupport::Inflector.pluralize(@singular).freeze - @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze - @human = ActiveSupport::Inflector.humanize(@element).freeze - @collection = ActiveSupport::Inflector.tableize(self).freeze + @unnamespaced = self.sub(/^#{namespace.name}::/, '') if namespace + @klass = klass + @singular = _singularize(self).freeze + @plural = ActiveSupport::Inflector.pluralize(@singular).freeze + @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze + @human = ActiveSupport::Inflector.humanize(@element).freeze + @collection = ActiveSupport::Inflector.tableize(self).freeze @partial_path = "#{@collection}/#{@element}".freeze - @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze - @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural).freeze - @i18n_key = self.underscore.to_sym + @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze + @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural).freeze + @i18n_key = self.underscore.to_sym end # Transform the model name into a more humane format, using I18n. By default, @@ -79,7 +79,9 @@ module ActiveModel # used to retrieve all kinds of naming-related information. def model_name @_model_name ||= begin - namespace = self.parents.detect { |n| n.respond_to?(:_railtie) } + namespace = self.parents.detect do |n| + n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming? + end ActiveModel::Name.new(self, namespace) end end diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb index 5f943729dd..a5ee2d6090 100644 --- a/activemodel/test/cases/naming_test.rb +++ b/activemodel/test/cases/naming_test.rb @@ -74,10 +74,6 @@ class NamingWithNamespacedModelInIsolatedNamespaceTest < ActiveModel::TestCase def test_param_key assert_equal 'post', @model_name.param_key end - - def test_recognizing_namespace - assert_equal 'Post', Blog::Post.model_name.instance_variable_get("@unnamespaced") - end end class NamingWithNamespacedModelInSharedNamespaceTest < ActiveModel::TestCase @@ -160,6 +156,40 @@ class NamingWithSuppliedModelNameTest < ActiveModel::TestCase end end +class NamingUsingRelativeModelNameTest < ActiveModel::TestCase + def setup + @model_name = Blog::Post.model_name + end + + def test_singular + assert_equal 'blog_post', @model_name.singular + end + + def test_plural + assert_equal 'blog_posts', @model_name.plural + end + + def test_element + assert_equal 'post', @model_name.element + end + + def test_collection + assert_equal 'blog/posts', @model_name.collection + end + + def test_human + assert_equal 'Post', @model_name.human + end + + def test_route_key + assert_equal 'posts', @model_name.route_key + end + + def test_param_key + assert_equal 'post', @model_name.param_key + end +end + class NamingHelpersTest < Test::Unit::TestCase def setup @klass = Contact diff --git a/activemodel/test/models/blog_post.rb b/activemodel/test/models/blog_post.rb index d289177259..46eba857df 100644 --- a/activemodel/test/models/blog_post.rb +++ b/activemodel/test/models/blog_post.rb @@ -1,10 +1,6 @@ module Blog - def self._railtie - Object.new - end - - def self.table_name_prefix - "blog_" + def self.use_relative_model_naming? + true end class Post diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 2bf24558a6..07f5fcdeb3 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -25,75 +25,75 @@ module ActiveSupport autoload :LocalCache, 'active_support/cache/strategy/local_cache' end - # Creates a new CacheStore object according to the given options. - # - # If no arguments are passed to this method, then a new - # ActiveSupport::Cache::MemoryStore object will be returned. - # - # If you pass a Symbol as the first argument, then a corresponding cache - # store class under the ActiveSupport::Cache namespace will be created. - # For example: - # - # ActiveSupport::Cache.lookup_store(:memory_store) - # # => returns a new ActiveSupport::Cache::MemoryStore object - # - # ActiveSupport::Cache.lookup_store(:mem_cache_store) - # # => returns a new ActiveSupport::Cache::MemCacheStore object - # - # Any additional arguments will be passed to the corresponding cache store - # class's constructor: - # - # ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache") - # # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache") - # - # If the first argument is not a Symbol, then it will simply be returned: - # - # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new) - # # => returns MyOwnCacheStore.new - def self.lookup_store(*store_option) - store, *parameters = *Array.wrap(store_option).flatten - - case store - when Symbol - store_class_name = store.to_s.camelize - store_class = - begin - require "active_support/cache/#{store}" - rescue LoadError => e - raise "Could not find cache store adapter for #{store} (#{e})" - else - ActiveSupport::Cache.const_get(store_class_name) - end - store_class.new(*parameters) - when nil - ActiveSupport::Cache::MemoryStore.new - else - store + class << self + # Creates a new CacheStore object according to the given options. + # + # If no arguments are passed to this method, then a new + # ActiveSupport::Cache::MemoryStore object will be returned. + # + # If you pass a Symbol as the first argument, then a corresponding cache + # store class under the ActiveSupport::Cache namespace will be created. + # For example: + # + # ActiveSupport::Cache.lookup_store(:memory_store) + # # => returns a new ActiveSupport::Cache::MemoryStore object + # + # ActiveSupport::Cache.lookup_store(:mem_cache_store) + # # => returns a new ActiveSupport::Cache::MemCacheStore object + # + # Any additional arguments will be passed to the corresponding cache store + # class's constructor: + # + # ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache") + # # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache") + # + # If the first argument is not a Symbol, then it will simply be returned: + # + # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new) + # # => returns MyOwnCacheStore.new + def lookup_store(*store_option) + store, *parameters = *Array.wrap(store_option).flatten + + case store + when Symbol + store_class_name = store.to_s.camelize + store_class = + begin + require "active_support/cache/#{store}" + rescue LoadError => e + raise "Could not find cache store adapter for #{store} (#{e})" + else + ActiveSupport::Cache.const_get(store_class_name) + end + store_class.new(*parameters) + when nil + ActiveSupport::Cache::MemoryStore.new + else + store + end end - end - def self.expand_cache_key(key, namespace = nil) - expanded_cache_key = namespace ? "#{namespace}/" : "" + def expand_cache_key(key, namespace = nil) + expanded_cache_key = namespace ? "#{namespace}/" : "" + + prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"] + if prefix + expanded_cache_key << "#{prefix}/" + end - prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"] - if prefix - expanded_cache_key << "#{prefix}/" + expanded_cache_key << retrieve_cache_key(key) + expanded_cache_key end - expanded_cache_key << - if key.respond_to?(:cache_key) - key.cache_key - elsif key.is_a?(Array) - if key.size > 1 - key.collect { |element| expand_cache_key(element) }.to_param - else - key.first.to_param - end - elsif key - key.to_param - end.to_s + private - expanded_cache_key + def retrieve_cache_key(key) + case + when key.respond_to?(:cache_key) then key.cache_key + when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param + else key.to_param + end.to_s + end end # An abstract cache store class. There are multiple cache store diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index b1b6de0613..5d7464c623 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -13,10 +13,10 @@ class CacheKeyTest < ActiveSupport::TestCase ENV['RAILS_CACHE_ID'] = 'c99' assert_equal 'c99/foo', ActiveSupport::Cache.expand_cache_key(:foo) assert_equal 'c99/foo', ActiveSupport::Cache.expand_cache_key([:foo]) - assert_equal 'c99/c99/foo/c99/bar', ActiveSupport::Cache.expand_cache_key([:foo, :bar]) + assert_equal 'c99/foo/bar', ActiveSupport::Cache.expand_cache_key([:foo, :bar]) assert_equal 'nm/c99/foo', ActiveSupport::Cache.expand_cache_key(:foo, :nm) assert_equal 'nm/c99/foo', ActiveSupport::Cache.expand_cache_key([:foo], :nm) - assert_equal 'nm/c99/c99/foo/c99/bar', ActiveSupport::Cache.expand_cache_key([:foo, :bar], :nm) + assert_equal 'nm/c99/foo/bar', ActiveSupport::Cache.expand_cache_key([:foo, :bar], :nm) ensure ENV['RAILS_CACHE_ID'] = nil end @@ -42,7 +42,7 @@ class CacheKeyTest < ActiveSupport::TestCase end end - def test_respond_to_cache_key + def test_expand_cache_key_respond_to_cache_key key = 'foo' def key.cache_key :foo_key @@ -50,6 +50,25 @@ class CacheKeyTest < ActiveSupport::TestCase assert_equal 'foo_key', ActiveSupport::Cache.expand_cache_key(key) end + def test_expand_cache_key_array_with_something_that_responds_to_cache_key + key = 'foo' + def key.cache_key + :foo_key + end + assert_equal 'foo_key', ActiveSupport::Cache.expand_cache_key([key]) + end + + def test_expand_cache_key_of_nil + assert_equal '', ActiveSupport::Cache.expand_cache_key(nil) + end + + def test_expand_cache_key_of_false + assert_equal 'false', ActiveSupport::Cache.expand_cache_key(false) + end + + def test_expand_cache_key_of_true + assert_equal 'true', ActiveSupport::Cache.expand_cache_key(true) + end end class CacheStoreSettingTest < ActiveSupport::TestCase diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 817fa39cab..0b72a7ed84 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -141,6 +141,10 @@ module Rails self end + def helpers_paths + config.helpers_paths + end + protected alias :build_middleware_stack :app diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index d652c6b7fe..335a0fb1b5 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -371,20 +371,28 @@ module Rails self.routes.default_scope = { :module => ActiveSupport::Inflector.underscore(mod.name) } self.isolated = true - unless mod.respond_to?(:_railtie) - name = engine_name - _railtie = self + unless mod.respond_to?(:railtie_namespace) + name, railtie = engine_name, self + mod.singleton_class.instance_eval do - define_method(:_railtie) do - _railtie - end + define_method(:railtie_namespace) { railtie } unless mod.respond_to?(:table_name_prefix) - define_method(:table_name_prefix) do - "#{name}_" - end + define_method(:table_name_prefix) { "#{name}_" } + end + + unless mod.respond_to?(:use_relative_model_naming?) + class_eval "def use_relative_model_naming?; true; end", __FILE__, __LINE__ + end + + unless mod.respond_to?(:railtie_helpers_paths) + define_method(:railtie_helpers_paths) { railtie.helpers_paths } + end + + unless mod.respond_to?(:railtie_routes_url_helpers) + define_method(:railtie_routes_url_helpers) { railtie.routes_url_helpers } end - end + end end end @@ -429,13 +437,6 @@ module Rails def helpers @helpers ||= begin helpers = Module.new - - helpers_paths = if config.respond_to?(:helpers_paths) - config.helpers_paths - else - paths["app/helpers"].existent - end - all = ActionController::Base.all_helpers_from_path(helpers_paths) ActionController::Base.modules_for_helpers(all).each do |mod| helpers.send(:include, mod) @@ -444,6 +445,14 @@ module Rails end end + def helpers_paths + paths["app/helpers"].existent + end + + def routes_url_helpers + routes.url_helpers + end + def app @app ||= begin config.middleware = config.middleware.merge_into(default_middleware_stack) diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb index e8fb1f3d98..f0991b99af 100644 --- a/railties/lib/rails/railtie.rb +++ b/railties/lib/rails/railtie.rb @@ -196,7 +196,7 @@ module Rails end def railtie_namespace - @railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:_railtie) } + @railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:railtie_namespace) } end end end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 22dbcf9644..e8081c977f 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -323,7 +323,7 @@ module RailtiesTest assert_equal "bukkits_", Bukkits.table_name_prefix assert_equal "bukkits", Bukkits::Engine.engine_name - assert_equal Bukkits._railtie, Bukkits::Engine + assert_equal Bukkits.railtie_namespace, Bukkits::Engine assert ::Bukkits::MyMailer.method_defined?(:foo_path) assert !::Bukkits::MyMailer.method_defined?(:bar_path) @@ -467,7 +467,7 @@ module RailtiesTest assert_nil Rails.application.load_seed end - test "using namespace more than once on one module should not overwrite _railtie method" do + test "using namespace more than once on one module should not overwrite railtie_namespace method" do @plugin.write "lib/bukkits.rb", <<-RUBY module AppTemplate class Engine < ::Rails::Engine @@ -484,7 +484,7 @@ module RailtiesTest boot_rails - assert_equal AppTemplate._railtie, AppTemplate::Engine + assert_equal AppTemplate.railtie_namespace, AppTemplate::Engine end test "properly reload routes" do |