Il modo migliore per aggiungere JavaScript specifico per una pagina in un’app Rails 3?

Rails 3 ha un JavaScript non invadente, che è abbastanza bello.

Ma mi stavo chiedendo quale sia il modo migliore per includere JavaScript aggiuntivo per una determinata pagina.

Ad esempio, dove avrei potuto fare precedentemente:

 "$('some_div').show();" %> 

Ora possiamo renderlo discreto con qualcosa di simile

  # then in some other file $('user_rating_positive').click(function() { $('some_div').show(); } 

Quindi immagino che la mia domanda sia dove / come includere quel JavaScript? Non voglio riempire il file application.js perché questo JavaScript è applicabile solo a questa vista. Dovrei includere un file JavaScript personalizzato per ogni pagina in qualche modo, o incollarlo in una variabile di istanza che l’intestazione cerca?

Quello che mi piace fare è includere il Javascript per visualizzazione in un content_for :head block e quindi yield a quel blocco nel layout dell’applicazione. Per esempio

Se è piuttosto breve allora:

 <% content_for :head do %>  <% end %> 

o, se più lungo, quindi:

 <% content_for :head do %>  <% end %> 

Quindi, nel tuo file di layout

  ... <%= yield :head %>  

Se vuoi includere javascript solo su una pagina, puoi ovviamente includerlo nella pagina inline, ma se vuoi raggruppare il tuo javascript e sfruttare la pipeline di asset, js minificati, è ansible farlo ed avere extra risorse js che vengono combinate e caricate solo su pagine specifiche dividendo i js in gruppi che si applicano solo in determinati controller / viste / sezioni del sito.

Sposta il tuo js in risorse in cartelle, con un file manifest separato per ciascuna, quindi se disponi di una libreria js di amministrazione che viene utilizzata solo nel back-end, puoi eseguire questa operazione:

  • risorse
    • javascript
      • Admin
        • … js
      • admin.js (manifest per il gruppo admin)
      • application.js (manifest per il gruppo globale di app)
      • globale
        • … js

nel file application.js esistente

 //= require jquery //= require jquery_ujs //= require_tree ./global // requires all js files in global folder 

in un nuovo file manifest admin.js

 //= require_tree ./admin // requires all js files in admin folder 

Assicurati che questo nuovo js manifest sia caricato modificando config / production.rb

 config.assets.precompile += %w( admin.js ) 

Quindi regola il layout della pagina in modo da poter includere alcuni j extra per il page head:

 <%= content_for :header %> 

Quindi nelle viste in cui si desidera includere questo gruppo js specifico (oltre al normale gruppo di applicazioni) e / o qualsiasi js, css ecc. Specifici della pagina:

 <% content_for :header do %> <%= javascript_include_tag 'admin' %> <% end %> 

Ovviamente puoi fare la stessa cosa con i CSS e raggrupparli in modo simile per applicarli solo ad alcune aree del sito.

Preferisco il seguente …

Nel tuo file application_helper.rb

 def include_javascript (file) s = " " content_for(:head, raw(s)) end 

e poi nella tua vista particolare (app / views / books / index.html.erb in questo esempio)

 <% include_javascript 'books/index.js' %> 

… Sembra funzionare per me.

Queste risposte mi hanno aiutato tantissimo! Se qualcuno vuole un po ‘di più …

  1. È necessario inserire i javascript nei manifesti se si desidera che siano precompilati. Tuttavia, se richiedi ogni file javascript da application.js.coffee tutti i javacsripts verranno caricati ogni volta che navighi su una pagina diversa, e lo scopo di fare javascript specifici della pagina verrà sconfitto.

Pertanto, è necessario creare il proprio file manifest (es. speciifc.js ) che richiederà tutti i file javascript specifici della pagina. Inoltre, modifica require_tree da application.js

app / Attività / javascripts / application.js

 //= require jquery //= require jquery_ujs //= require_tree ./global 

app / Attività / javascripts / specific.js

 //= require_tree ./specific 

Quindi, nei tuoi environments/production.rb aggiungi questo manifest alla lista precompilata con l’opzione config,

config.assets.precompile += %w( specific.js )

Fatto! Tutti i javascript condivisi che devono sempre essere caricati verranno inseriti in app/assets/javascripts/global folder e nei javascript di pagina specifici in app/assets/javascripts/specific . Puoi semplicemente chiamare i javascript specifici della pagina dalla vista come

<%= javascript_include_tag "specific/whatever.js" %> //.js è facoltativo.

Questo è sufficiente, ma volevo usare anche i javascript_include_tag params[:controller] . Quando crei controller, un file coffeescript associato viene generato in app/assets/javascripts come altre persone menzionate. Esistono javascript specifici del controller , che vengono caricati solo quando l’utente raggiunge la specifica vista del controller.

Così ho creato un altro manifest controller-specific.js

app / Attività / javascripts / Controller-specific.js

//= require_directory .

Ciò includerà tutti i coffeescripts generati automaticamente associati ai controller. Inoltre, è necessario aggiungerlo all’elenco precompilato.

config.assets.precompile += %w( specific.js controller-specific.js )

Se non si desidera utilizzare la pipeline degli asset o il lavoro complesso per ottenere quel javascript specifico della pagina necessario (io simpatizzo), il modo più semplice e robusto, che raggiunge lo stesso risultato delle risposte precedenti ma con meno codice, è solo per uso:

 <%= javascript_include_tag "my_javascipt_file" %> 

Nota: questo richiede un’ulteriore richiesta http per tag di inclusione rispetto alle risposte che utilizzano content_for :head

Dai un’occhiata alla gem pluggable_js . Potresti trovare questa soluzione più facile da usare.

La mia comprensione è che la pipeline di asset ha lo scopo di ridurre il tempo di caricamento della pagina mischiando tutti i js insieme in un file (minimizzato). Mentre questo può sembrare ripugnante in superficie, è in realtà una caratteristica che esiste già in lingue popolari come C e Ruby. Cose come i tag “include” hanno lo scopo di prevenire l’inclusione multipla di un file e di aiutare i programmatori a organizzare il loro codice. Quando scrivi e compili un programma in C, tutto quel codice è presente in ogni parte del tuo programma in esecuzione, ma i metodi vengono caricati in memoria solo quando viene utilizzato quel codice. In un certo senso, un programma compilato non include nulla per garantire che il codice sia ben modulare. Rendiamo modulare il codice scrivendo i nostri programmi in questo modo, e il sistema operativo carica solo in memoria gli oggetti e i metodi di cui abbiamo bisogno per una determinata località. Esiste anche una “inclusione specifica al metodo”? Se la tua app per le rotaie è riposante, questo è essenzialmente ciò che stai chiedendo.

Se scrivi il tuo javascript in modo da aumentare il comportamento degli elementi HTML sulla pagina, queste funzioni sono “specifiche della pagina” in base alla progettazione. Se esiste un codice complicato che è stato scritto in modo tale da essere eseguito indipendentemente dal suo contesto, prendere in considerazione l’idea di associare il codice a un elemento html (è ansible utilizzare il tag body, come descritto nel metodo Garber-Irish ). Se una funzione viene eseguita in modo condizionale, le prestazioni saranno probabilmente inferiori rispetto a tutti quei tag di script aggiuntivi.

Sto pensando di usare la gem di paloma , come descritto nel progetto di app per rails . Quindi puoi rendere il tuo javascript specifico per la pagina includendo funzioni specifiche della pagina in un callback paloma:

 Paloma.callbacks['users']['new'] = function(params){ // This will only run after executing users/new action alert('Hello New Sexy User'); }; 

Tu usi le rotaie, quindi so che ami le gemme 🙂

Non dovresti caricare i file JS o CSS al di fuori della pipeline degli asset perché perdi funzionalità importanti che rendono Rails così eccezionale. E non hai bisogno di un’altra gem. Credo nell’usare il minor numero ansible di gemme e non è necessario utilizzare una gem qui.

Quello che vuoi è noto come “Javascript specifico del controller” (“Javascript specifico per azione è incluso nella parte inferiore) .Questo ti consente di caricare un file JavaScript specifico per un determinato CONTROLLER.Il tentativo di connettere il tuo Javascript a una vista è una specie di .. all’indietro e non segue il modello di progettazione MVC. Si desidera associarlo ai controller o alle azioni all’interno dei controller.

Sfortunatamente, per qualsiasi motivo, gli sviluppatori di Rails hanno deciso che, per impostazione predefinita, ogni pagina caricherà ogni file JS che si trova nella directory delle risorse. Perché hanno deciso di farlo invece di abilitare “Javascript specifico del controller” di default non lo saprò mai. Questo viene fatto attraverso il file application.js, che include la seguente riga di codice per impostazione predefinita:

 //= require_tree . 

Questo è noto come una direttiva . È ciò che le ruote dentate usano per caricare ogni file JS nella directory assets / javascripts. Per impostazione predefinita, le ruote dentate caricano automaticamente application.js e application.css e la direttiva require_tree carica ogni file JS e Coffee nelle rispettive directory.

NOTA: quando lo scaffold (se non si è in fase di impalcatura, ora è un buon momento per iniziare), Rails genera automaticamente un file di caffè per te, per il controller dello scaffold. Se si desidera generare un file JS standard invece di un file caffè , rimuovere la gem caffè abilitata per impostazione predefinita nel proprio file Gem e lo scaffold crea invece file JS.

Ok, quindi il primo passaggio per abilitare “Javascript specifico del controller” è rimuovere il codice require_tree dal file application.js, OPPURE modificarlo in una cartella all’interno della directory assets / javascripts se sono ancora necessari file JS globali. IE:

 //= require_tree ./global 

Passaggio 2: accedi al tuo file config / initializers / assets.rb e aggiungi quanto segue:

 %w( controllerone controllertwo controllerthree ).each do |controller| Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"] end 

Inserisci i nomi dei controller che desideri.

Passaggio 3: Sostituisci javascript_include_tag nel file application.html.erb con questo (nota la parte params [: controller]:

 <%= javascript_include_tag 'application', params[:controller], 'data-turbolinks-track': 'reload' %> 

Riavvia il tuo server e viola! Il file JS che è stato generato con lo scaffold ora verrà caricato solo quando viene chiamato quel controller.

È necessario caricare un file JS specifico su un’azione specifica nel controller , IE / articoli / nuovi ? Fatelo invece:

application.html.erb :

 <%= javascript_include_tag "#{controller_name}/#{action_name}" if AppName::Application.assets.find_asset("#{controller_name}/#{action_name}") %> 

config / initializers / assets.rb :

 config.assets.precompile += %w(*/*) 

Quindi aggiungi una nuova cartella con lo stesso nome del tuo controller nella cartella assets / javascript e inserisci il tuo file js con lo stesso nome dell’azione all’interno. Lo caricherà quindi su quell’azione specifica.

Ok, quindi forse questo è il peggior lavoro in assoluto, ma ho creato un metodo controller che ha appena reso disponibile il file .js

controllore

 def get_script render :file => 'app/assessts/javascripts/' + params[:name] + '.js' end def get_page @script = '/' + params[:script_name] + '.js?body=1' render page end 

vista

 %script{:src => @script, :type => "text/javascript"} 

se per qualche ragione non vogliamo farlo, fammelo sapere

Il modo preferito per aggiungere JS è nel footer, quindi puoi farlo in questo modo:

show.html.erb:

 <% content_for :footer_js do %> This content will show up in the footer section <% end %> 

layout / application.html.erb

 <%= yield :footer_js %>