Rely on a public contract between railties instead of accessing railtie methods directly.

This commit is contained in:
José Valim 2011-11-23 19:06:45 +00:00
parent 3ee0116c94
commit fd86a1b6b0
12 changed files with 94 additions and 54 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -141,6 +141,10 @@ module Rails
self
end
def helpers_paths
config.helpers_paths
end
protected
alias :build_middleware_stack :app

View File

@ -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
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
@ -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)

View File

@ -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

View File

@ -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