2011-09-06 9 views
13

Moja produkcja asset_host config wygląda następująco:szyny 3.1 nie można skompilować aktywa na prod powodu aktywów gospodarza config

config.action_controller.asset_host = Proc.new { |source, request| 
    if request.ssl? 
     "#{request.protocol}#{request.host_with_port}" 
    else 
     "#{request.protocol}assets#{(source.length % 4) + 1}.example.com" 
    end 
    } 

... co jest mniej lub bardziej wprost z dokumentów:

http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html

Kiedy idę do aktywów: prekompilacji, otrzymuję to:

$ RAILS_ENV=production bundle exec rake assets:precompile 
rake aborted! 
This asset host cannot be computed without a request in scope. Remove 
the second argument to your asset_host Proc if you do not need the 
request. 

.... exce pt, że naprawdę nie mogę usunąć 2. arg, ponieważ muszę wiedzieć, czy wniosek jest ssl, czy nie. W związku z tym rozumiem, że żądanie nie jest dostępne podczas zadania rake, aby wygenerować aktywa ....

Jak mogę wydostać się z tego haczyka 22?

Odpowiedz

18

to się stanie, gdy (1) swoje aktywa używać ścieżek, na przykład:

background:url(image_path('awesome-background.gif')) 

i (2) Twój asset_host jest ustawiony na lambda/proc wymagającej drugi argument (request).

Dostępne opcje to usunięcie argumentu request (jeśli w rzeczywistości go nie używasz) lub uczynienie go opcjonalnym (i obsługa przypadku, w którym jest to nil). Jest łatwy w Ruby 1.9 (i powinno być łatwiejsze, patrz uwagi):

config.action_controller.asset_host = ->(source, request = nil, *_){ 
    # ... just be careful that request can be nil 
} 

Jeśli chcesz być zgodny z Ruby 1.8, nie ma bezpośredni sposób, aby utworzyć proc/lambda z parametrami z domyślnych, ale można użyć:

config.action_controller.asset_host = Proc.new do |*args| 
    source, request = args 
    # ... 
end 

lub zrobić to za pomocą metody:

def MyApp.compute_asset_host(source, request = nil) 
    # ... 
end 

config.action_controller.asset_host = MyApp.method(:compute_asset_host) 

Uwagi:

  1. Twój blok może powrócić nil oznaczać „domyślnego hosta”, nie ma potrzeby korzystania "#{request.protocol}#{request.host_with_port}"
  2. W teorii nie ma potrzeby, aby określić protokół; adres URL zaczynający się od // powinien korzystać z domyślnego protokołu (http lub https). Mówię "powinien", ponieważ wygląda na to, że wygląda na IE <= 8 will download the css assets twice i mam problemy z plikiem PDFkit.

więc w danym przypadku swoje asset_host można uprościć do:

config.action_controller.asset_host = Proc.new { |source, request = nil, *_| 
    "//assets#{(source.length % 4) + 1}.example.com" if request && !request.ssl? 
} 

Edytuj: Użyj lambda albo też *_ uniknąć bug feature of Ruby.

+0

Czy nie powinno być 'if request && request.ssl?' Be 'unless request && request.ssl?' –

+0

@EricKoslow: Oh, racja, odwróciłem część warunku. Naprawiono, myślę :-) –

+1

To jest fantastyczna odpowiedź, proszę oznaczyć jako poprawne! –

3

Za wersję ruby ​​1.8.x, @ Marc-Andre'a method(:compute_asset_host) nie zadziałała dla mnie.Mimo że metoda została zdefiniowana bezpośrednio powyżej, podniesiono NameError: undefined method `compute_asset_host' for class `Object'.

Oto co pracował dla mnie:

config.action_controller.asset_host = Proc.new do |*args| 
    source, request = args 
    if request.try(:ssl?) 
    'ssl.cdn.mysite.com' 
    else 
    'cdn%d.mysite.com' % (source.hash % 4) 
    end 
end 
+0

Edytowałem mój przykład z wyraźnym zakresem, aby było jaśniejsze. Twój sugerowany Proc jest dobry, więc również go włączyłem. Dzięki. –

Powiązane problemy