8

我正在更新Rails 3應用程序以使用Rails 3.1,並且正在使用新的資產管道作爲其中的一部分。到目前爲止,除了一個我無法解決的令人討厭的問題之外,我已經完成了所有工作。在部署到子URI時在Rails 3.1中損壞的預編譯資產

應用程序及其所有資產在開發中工作正常,但在生產中它使用Passenger(http://the-host/sub-uri/)部署到子URI。問題在於資源是在部署期間預先編譯的,我的一個CSS(嗯,它是一個.css.scss文件)文件正在利用sass-rails gem的image-url幫手。在

body { background-image: image-url("bg.png"); } 

結果是:由於在預編譯過程中,路徑是硬編碼到預編譯的CSS文件,子URI是沒有考慮到:

在我.css.scss文件編譯application-<md5-hash-here>.css文件:

body { background-image: url(/assets/bg.png); } 

它應該是什麼使它正常工作:

body { background-image: url(/sub-uri/assets/bg.png); } 

這種情況只是要求太多嗎?如果是這樣,我將不得不切換回舊的非資產流水線方式,只需從public提供我的圖像和CSS。然而,這似乎是應該考慮和解決的事情......?我錯過了解決方案嗎?


編輯1:我應該注意使用erb solution,而不是產生同樣的結果,正如人們所期望的那樣。


編輯2:響應貝努瓦閣樓的評論

沒有,問題是不相關的config.assets.prefix。我試圖設置(到/sub-uri/assets而不是默認的/assets),但事實證明這是錯誤的做法 - 它似乎已經與Rails應用程序的根,而不是服務器相關。刪除(並因此返回到默認值)已經修復了造成的所有奇怪問題(並且有很多,所有資產都以/sub-uri/sub-uri/assets結尾 - 這非常奇怪)。唯一的問題是image-url助手和朋友在預編譯時不會選擇子URI。不用說,這是合乎邏輯的,因爲當它被預編譯時,它不可能知道當它在Passenger下運行時,它將以這種方式配置。我的問題是如何通知它這一點,從而結束預編譯結果中的正確路徑。如果確實可以做到。

我目前的解決方法是在CSS中引用iamge,如下所示:url(../images/bg.png)並將其置於非流水線public/images的位置。很不理想,因爲它不會受益於指紋和管道所提供的一切。

+0

你試過這個嗎? http://stackoverflow.com/questions/7295744/how-to-deploy-rails-3-1-app-in-a-subdirectory –

+0

該應用程序本身部署得很好(它確實使用RailsBaseURI方法,因爲它是乘客文檔推薦)。從正在運行的應用程序中鏈接到的所有資源,如使用'image_tag'等的圖像等都沒有問題。唯一的問題是從CSS內引用的圖像 - 在預編譯資產時它不知道子URI。正因爲如此,我需要一個解決方案。 –

+0

所以你的問題是'image-uri'幫手沒有拿起'config.assets.prefix'? –

回答

4

最後我已經制定了一些解決方法。

1)從https://github.com/rails/sass-rails/issues/17看起來這可能會在sass-rails中得到修復。我已經在上面的鏈接中建議的補丁的行中貼上了猴子補丁的助手。我只需在deploy.rb的資產預編譯行中設置所需的環境變量即可。

我做我所有的猴子修補在一個單一的文件config/initializers/gem_patches.rb。在這個文件中我修補了這個方法:

module Sass 
    module Rails 
    module Helpers 
     protected 
     def public_path(asset, kind) 
     path = options[:custom][:resolver].public_path(asset, kind.pluralize) 
     path = ENV['PRODUCTION_URI'] + path if ENV['PRODUCTION_URI'] 
     path 
     end 
    end 
    end 
end 

2)另外,如果你確定在CSS中嵌入圖片,改變樣式表有一個.erb擴展,並更換image-url("bg.png")url(<%= asset_data_uri "bg.png" %>)將沒有任何工作需要改變sass-rails。 asset-data-uri不存在作爲一個純粹的Sass功能,所以你必須使用Rails幫手asset_data_uri

+0

關於第二點的好消息 - 這會起作用,這是我從未考慮過的事情。絕對不是理想的,但是一個有效的解決方法。對於第1點,你能否澄清'deploy.rb'中變量的設置? –

+0

我剛剛解決了你的意思......你是從你的deploy.rb文件手動運行預編譯任務,對吧?我使用提供的'load'deploy/assets''來加載我的Capfile文件 - 所以在'deploy.rb'中,我不應該在那裏顯示環境變量設置。我確定我可以找到別的地方來設置它。即使在最糟糕的情況下,您也給我提出了一個需要注意的問題,充其量我認爲這是現在的答案。謝謝:) –

+0

沒錯。在我的'deploy.rb'中,我有一個'deploy'之後的資源預編譯:update_code「'任務。我運行cd#{release_path};捆綁exec rake資產:預編譯RAILS_ENV = production PRODUCTION_URI ='/ myapp'「'然後在我的猴子補丁helpers.rb中,我只是拿起'ENV ['PRODUCTION_URI']' 。 – 2011-09-10 18:51:38

0

經過一番挖掘,我發現了這個問題。問題出現在Rails中,特別是Sprockets :: Helpers :: RailsHelper :: AssetPaths#compute_public_path。 Sprockets :: Helpers :: RailsHelper :: AssetPaths繼承自ActionView :: AssetPaths並覆蓋了很多方法。當通過Sass :: Rails :: Resolver調用compute_public_path時#public_path方法是sass-rails,rails sprocket helper可以完成解析資產的任務。 Sprockets :: Helpers :: RailsHelper :: AssetPaths#compute_public_path推遲超級,它是ActionView :: AssetPaths#compute_public_path。在這種方法中有has_request的條件?上rewrite_relative_url_root如下所示:

def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil) 
    ... 
    source = rewrite_relative_url_root(source, relative_url_root) if has_request? 
    ... 
end 

def relative_url_root 
    config = controller.config if controller.respond_to?(:config) 
    config ||= config.action_controller if config.action_controller.present? 
    config ||= config 
    config.relative_url_root 
end 

如果看一下rewrite_relative_url_root的內部它依賴於請求是存在和來自控制器變量推導它爲了解決相對URL根的能力。問題是,當鏈輪解決這些資產的問題時,它沒有控制器,因此沒有要求。

上面的解決方案對我來說不適用於開發模式。下面是我使用,使之成爲目前工作的解決方案:

module Sass 
    module Rails 
    module Helpers 
     protected 
     def public_path(asset, kind) 
     resolver = options[:custom][:resolver] 
     asset_paths = resolver.context.asset_paths 
     path = resolver.public_path(asset, kind.pluralize) 
     if !asset_paths.send(:has_request?) && ENV['RAILS_RELATIVE_URL_ROOT'] 
      path = ENV['RAILS_RELATIVE_URL_ROOT'] + path 
     end 
     path 
     end 
    end 
    end 
end 
+0

我是否認爲這與其他答案基本相同,只是實現了一個有點不同嗎? (或許天真地少一點,而不是另一種方法導致我的任何問題...) –

+0

https://github.com/rails/rails/pull/2977 –

2

在最新的Rails 3.1.3,你需要現在猴子修補不同的模塊,它的工作

這是什麼我做

module Sprockets 
    module Helpers 
    module RailsHelper 

     def asset_path(source, options = {}) 
     source = source.logical_path if source.respond_to?(:logical_path) 
     path = asset_paths.compute_public_path(source, asset_prefix, options.merge(:body => true)) 
     path = options[:body] ? "#{path}?body=1" : path 
     if !asset_paths.send(:has_request?) 
      path = ENV['RAILS_RELATIVE_URL_ROOT'] + path if ENV['RAILS_RELATIVE_URL_ROOT'] 
     end 
     path 
     end 

    end 
    end 
end 

在我deploy.rb我:

desc "precompile the assets" 
namespace :assets do 
    task :precompile_assets do 
    run "cd #{release_path} && rm -rf public/assets/* && RAILS_ENV=production bundle exec rake assets:precompile RAILS_RELATIVE_URL_ROOT='/my_sub_uri'" 
    end 
end 
before "deploy:symlink", "assets:precompile_assets" 
+3

謝謝。我發現在Rails 3.2中我們不需要這個補丁。只需運行命令'bundle exec rake assets:precompile RAILS_RELATIVE_URL_ROOT ='/ my_sub_uri'「'並且它可以工作 –

+0

感謝@SiweiShen,對於capistrano我在deploy.rb中添加了一個任務,在deploy之前運行:assets:precompile, asset_env,「#{asset_env} RAILS_RELATIVE_URL_ROOT =/my_sub_uri」' – Cam

2

我用Rails 3.1.3並部署到蘇b-URI成功。 我沒有猴子補丁任何東西。

該設置的關鍵問題已被更好地討論here。正如你所看到的,該解決方案已應用於Rails 3.2,並且從未回到3.1.4。

但是,我來到一個解決方案,使用Rails 3.1.3,適用於我的設置。

試試這個:(我不是專家,只是想有助於解決我麻煩了好幾個小時的問題...)

environment.rb中:

#at top: 
ENV['RAILS_RELATIVE_URL_ROOT'] = '/rais' 

生產。RB:

config.assets.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] ? ENV['RAILS_RELATIVE_URL_ROOT'] + '/assets' : '/assets' 

的routes.rb:

Rais::Application.routes.draw do 
     scope ENV['RAILS_RELATIVE_URL_ROOT'] || '/' do #see config/environment.rb 
      <<resources here>> 
     end 
    end 

正如你所看到的,我已經把assets.prefix內production.rb,而不是在application.rb中 之後,你做的事:

rake assets:clear 
rake assets:precompile 

比,測試與控制檯:

RAILS_ENV=production rails console 

結果:

foo = ActionView::Base.new 
foo.stylesheet_link_tag 'application' 
=> "<link href=\"/rais/assets/layout.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"/rais/assets/application.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />" 
foo.image_tag('arrow-up.png') 
=> "<img alt=\"Arrow-up\" src=\"/rais/assets/arrow-up-ca314ad9b991768ad2b9dcbeeb8760de.png\" />" 
相關問題