8

Rails3.1を使用するようにRails3アプリを更新している最中であり、その一環として、新しいアセットパイプラインを利用しています。これまでのところ、解決できないかなり厄介な問題を除けば、すべてが機能しています。

アプリケーションとそのすべてのアセットは、開発では正常に機能しますが、本番環境では、Passenger()を使用してサブURIにデプロイされhttp://the-host/sub-uri/ます。これに伴う問題は、アセットがデプロイ中にプリコンパイルされ、CSS(まあ、それは.css.scssファイルです)ファイルの1つがgemのimage-urlヘルパーを利用していることです。sass-railsプリコンパイルプロセス中に、パスがプリコンパイルされたCSSファイルにハードコードされるため、サブURIは考慮されません。

私の.css.scssファイル:

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

コンパイルされたapplication-<md5-hash-here>.cssファイルの結果:

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

正しく機能させるにはどうすればよいですか。

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

このシナリオは、質問が多すぎますか?もしそうなら、私は古い非アセットパイプラインの方法に切り替えて、からの画像とCSSを提供する必要がありpublicます。しかし、それは考えられて解決されるべきもののように思えます...?私は解決策を逃していますか?


編集1:代わりにerbソリューションを使用すると、予想どおり同じ結果が得られることに注意してください。


編集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です。フィンガープリントやパイプラインが提供するすべてのものの恩恵を受けないため、ほとんど理想的ではありません。

4

4 に答える 4

4

最後に、いくつかの回避策/解決策を考え出しました。

1)https://github.com/rails/sass-rails/issues/17から、これはsass-railsで修正される可能性があるようです。上記のリンクで提案されたパッチに沿って、helpers.rbにモンキーパッチを適用しました。のアセットプリコンパイル行で必要な環境変数を設定するだけですdeploy.rb

私はすべてのモンキーパッチを1つのファイルで行います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")sass url(<%= asset_data_uri "bg.png" %>)-railsを変更しなくても機能します。 asset-data-uri純粋なSass関数としては存在しないため、Railsヘルパーを使用する必要がありますasset_data_uri

于 2011-09-10T13:59:39.933 に答える
2

最新のRails3.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"
于 2011-12-06T10:06:27.877 に答える
2

Rails 3.1.3を使用していて、サブURIに正常にデプロイしています。モンキーパッチは何もしていません。

この設定の主な問題については、ここで詳しく説明しています。ご覧のとおり、ソリューションはRails 3.2に適用され、3.1.4にバックポートされることはありませんでした。

しかし、私は自分のセットアップで機能するRails3.1.3を使用したソリューションに到達しました。

これを試してみてください:( 私は専門家ではなく、何時間も私を悩ませてきた問題の解決に貢献しようとしているだけです...)

environment.rb:

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

Production.rb:

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

ルート.rb:

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

ご覧のとおり、assets.prefixをapplication.rbではなくproduction.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\" />" 
于 2012-08-25T14:35:23.713 に答える
0

少し掘り下げてみたところ、問題が見つかりました。問題はRails、特にSprockets :: Helpers :: RailsHelper :: AssetPaths#compute_public_pathにあります。Sprockets :: Helpers :: RailsHelper::AssetPathsはActionView::AssetPathsを継承し、いくつかのメソッドをオーバーライドします。Sass :: Rails :: Resolver#public_pathメソッドがsass-railsを介してcompute_public_pathが呼び出されると、railsスプロケットヘルパーがアセットを解決するタスクを引き受けます。Sprockets :: Helpers :: RailsHelper :: AssetPaths#compute_public_pathは、ActionView :: AssetPaths#compute_public_pathであるsuperに依存します。このメソッドには、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ルートを解決するために、存在する要求と、それをコントローラー変数から派生させる機能に依存しています。問題は、スプロケットがsassのこれらのアセットを解決するときに、コントローラーが存在しないため、要求がないことです。

上記の解決策は、私にとって開発モードでは機能しませんでした。これが私が今のところそれを機能させるために使用している解決策です:

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
于 2011-09-10T20:13:47.147 に答える