2011-09-06 10 views
13

La mia produzione asset_host config si presenta così:rotaie 3.1 non può compilare asset su prod a causa di un'attività di configurazione dell'host

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 
    } 

... che è più o meno direttamente dai documenti:

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

Quando vado ai beni: precompilare, ottengo questo:

$ 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 che non riesco davvero a rimuovere il secondo arg perché ho bisogno di sapere se la richiesta è ssl o no. Detto questo, capisco che una richiesta non è presente durante l'attività rake per generare le risorse ....

Quindi, come faccio a uscire da questo fermo 22?

risposta

18

Questo avverrà quando (1) le risorse utilizzare percorsi, ad esempio:

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

e (2) la tua asset_host è impostato su un lambda/proc che richiede il secondo argomento (request).

Le opzioni consentono di rimuovere l'argomento request (se non lo si utilizza effettivamente) o renderlo facoltativo (e gestire il caso in cui è nil). Questo è facile in Ruby 1.9 (e dovrebbe essere più facile, vedi note):

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

Se si vuole essere compatibile con Ruby 1.8, non v'è alcun modo diretto per creare un Proc/lambda con parametri con valori predefiniti, ma è possibile utilizzare:

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

O impiegando un metodo:

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

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

Note:

  1. tuo blocco può tornare nil a significare il "host predefinito", senza bisogno di usare "#{request.protocol}#{request.host_with_port}"
  2. In teoria non è necessario specificare il protocollo; un url che inizia con // deve utilizzare il protocollo predefinito (http o https). Sto dicendo "dovrebbe" come sembra IE <= 8 will download the css assets twice e ho avuto problemi con PDFkit.

Quindi nel tuo caso particolare, il vostro asset_host può essere semplificata:

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

Edit: Usare un lambda, altrimenti il ​​*_ per evitare una bug feature of Ruby.

+0

Non dovrebbe che 'se richiesta && request.ssl?' Essere 'unless request && request.ssl?' –

+0

@EricKoslow: Oh, giusto, ho invertito parte della condizione. Risolto, penso :-) –

+1

Questa è una risposta fantastica, si prega di contrassegnare come corretta! –

3

Per ruby ​​1.8.x, la tecnica di @ Marc-Andre method(:compute_asset_host) non ha funzionato per me.Anche se il metodo è stato definito direttamente sopra, è stato generato NameError: undefined method `compute_asset_host' for class `Object'.

Ecco cosa ha funzionato per me:

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

Ho modificato il mio esempio con un ambito esplicito, per renderlo più chiaro. Il tuo Proc suggerito è buono, quindi l'ho anche incorporato. Grazie. –

Problemi correlati