From a132229d7b4382d9ffe8847fa58f469cb8f2ecfc Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 22 Jul 2010 22:11:32 +0200 Subject: [PATCH] Added ability to set asset_path for engines --- .../action_dispatch/testing/test_request.rb | 2 +- .../action_view/helpers/asset_tag_helper.rb | 3 + .../test/template/asset_tag_helper_test.rb | 23 +++++++ railties/lib/rails/application.rb | 14 ++--- .../lib/rails/application/configuration.rb | 12 ++++ railties/lib/rails/engine.rb | 23 ++++++- railties/lib/rails/engine/configuration.rb | 2 +- .../test/application/configuration_test.rb | 15 +++++ railties/test/railties/engine_test.rb | 60 +++++++++++++++++++ 9 files changed, 141 insertions(+), 13 deletions(-) diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb index b3e67f6e36..c587a36930 100644 --- a/actionpack/lib/action_dispatch/testing/test_request.rb +++ b/actionpack/lib/action_dispatch/testing/test_request.rb @@ -10,7 +10,7 @@ module ActionDispatch end def initialize(env = {}) - env = Rails.application.env_defaults.merge(env) if defined?(Rails.application) + env = Rails.application.env_config.merge(env) if defined?(Rails.application) super(DEFAULT_ENV.merge(env)) self.host = 'test.host' diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index a3c43d3e93..3329a8b368 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -727,6 +727,9 @@ module ActionView source += ".#{ext}" if rewrite_extension?(source, dir, ext) source = "/#{dir}/#{source}" unless source[0] == ?/ + if controller.respond_to?(:env) && controller.env["action_dispatch.asset_path"] + source = rewrite_asset_path(source, controller.env["action_dispatch.asset_path"]) + end source = rewrite_asset_path(source, config.asset_path) has_request = controller.respond_to?(:request) diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index 6d5e4893c4..2b83cfe1a9 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -387,6 +387,15 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal %(Rails), image_tag("rails.png") end + def test_env_asset_path + @controller.config.asset_path = "/assets%s" + def @controller.env; @_env ||= {} end + @controller.env["action_dispatch.asset_path"] = "/omg%s" + + expected_path = "/assets/omg/images/rails.png" + assert_equal %(Rails), image_tag("rails.png") + end + def test_proc_asset_id @controller.config.asset_path = Proc.new do |asset_path| "/assets.v12345#{asset_path}" @@ -396,6 +405,20 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal %(Rails), image_tag("rails.png") end + def test_env_proc_asset_path + @controller.config.asset_path = Proc.new do |asset_path| + "/assets.v12345#{asset_path}" + end + + def @controller.env; @_env ||= {} end + @controller.env["action_dispatch.asset_path"] = Proc.new do |asset_path| + "/omg#{asset_path}" + end + + expected_path = "/assets.v12345/omg/images/rails.png" + assert_equal %(Rails), image_tag("rails.png") + end + def test_image_tag_interpreting_email_cid_correctly # An inline image has no need for an alt tag to be automatically generated from the cid: assert_equal '', image_tag("cid:thi%25%25sis@acontentid") diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 300d4c6ab9..7c590b701e 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -124,16 +124,12 @@ module Rails alias :build_middleware_stack :app - def call(env) - env["action_dispatch.routes"] = routes - app.call(env.reverse_merge!(env_defaults)) - end - - def env_defaults - @env_defaults ||= { + def env_config + @env_config ||= super.merge({ "action_dispatch.parameter_filter" => config.filter_parameters, - "action_dispatch.secret_token" => config.secret_token - } + "action_dispatch.secret_token" => config.secret_token, + "action_dispatch.asset_path" => nil + }) end def initializers diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 7e34a16487..29fa9d14eb 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -25,6 +25,18 @@ module Rails @middleware = app_middleware end + def asset_path=(value) + action_mailer.asset_path = value if respond_to?(:action_mailer) && action_mailer + action_controller.asset_path = value if respond_to?(:action_controller) && action_controller + super(value) + end + + def asset_host=(value) + action_mailer.asset_host = value if action_mailer + action_controller.asset_host = value if action_controller + super(value) + end + def encoding=(value) @encoding = value if "ruby".encoding_aware? diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index d4a654fd08..6b1e21a798 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -147,6 +147,19 @@ module Rails # # Now, Engine will get only requests that were not handled by application. # + # == Asset path + # + # When you use engine with its own public directory, you will probably want to copy or symlink it + # to application's public directory. To simplify generating paths for assets, you can set asset_path + # for an Engine: + # + # class MyEngine::Engine < Rails::Engine + # config.asset_path = "/my_engine/%s" + # end + # + # With such config, asset paths will be automatically modified inside Engine: + # image_path("foo.jpg") #=> "/my_engine/images/foo.jpg" + # class Engine < Railtie autoload :Configurable, "rails/engine/configurable" autoload :Configuration, "rails/engine/configuration" @@ -219,8 +232,14 @@ module Rails end def call(env) - env["action_dispatch.routes"] = routes - app.call(env) + app.call(env.merge!(env_config)) + end + + def env_config + @env_config ||= { + 'action_dispatch.routes' => routes, + 'action_dispatch.asset_path' => config.asset_path + } end def routes diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index bf3ad1f26b..4588c27277 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -5,7 +5,7 @@ module Rails class Configuration < ::Rails::Railtie::Configuration attr_reader :root attr_writer :eager_load_paths, :autoload_once_paths, :autoload_paths - attr_accessor :middleware, :plugins + attr_accessor :middleware, :plugins, :asset_path def initialize(root=nil) super() diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 63d53fff90..6bf56f7052 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -260,5 +260,20 @@ module ApplicationTests get "/" assert_not_equal res, last_response.body end + + test "config.asset_path is not passed through env" do + make_basic_app do |app| + app.config.asset_path = "/omg%s" + end + + class ::OmgController < ActionController::Base + def index + render :inline => "<%= image_path('foo.jpg') %>" + end + end + + get "/" + assert_equal "/omg/images/foo.jpg", last_response.body + end end end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 4257a9fa83..3df6e110d5 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -199,5 +199,65 @@ module RailtiesTest assert_equal Rails.application.routes, env['action_dispatch.routes'] end + + test "it allows to set asset_path" do + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + config.asset_path = "/bukkits%s" + end + end + RUBY + + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + match "/foo" => "foo#index" + end + RUBY + + @plugin.write "app/controllers/foo_controller.rb", <<-RUBY + class FooController < ActionController::Base + def index + render :index + end + end + RUBY + + @plugin.write "app/views/foo/index.html.erb", <<-RUBY + <%= compute_public_path("/foo", "") %> + <%= image_path("foo.png") %> + <%= javascript_include_tag("foo") %> + <%= stylesheet_link_tag("foo") %> + RUBY + + + app_file "app/controllers/bar_controller.rb", <<-RUBY + class BarController < ActionController::Base + def index + render :index + end + end + RUBY + + app_file "app/views/bar/index.html.erb", <<-RUBY + <%= compute_public_path("/foo", "") %> + RUBY + + add_to_config 'config.asset_path = "/omg%s"' + + boot_rails + + env = Rack::MockRequest.env_for("/foo") + response = Bukkits::Engine.call(env) + stripped_body = response[2].body.split("\n").map(&:strip).join("\n") + + expected = "/omg/bukkits/foo\n" + + "/omg/bukkits/images/foo.png\n" + + "\n" + + "" + assert_equal expected, stripped_body + + end end end