2015-02-23 15 views
5

avevo bisogno di aggiungere un semplice cambiamento di foo_path, quindi ho fatto questo:Come posso sovrascrivere globalmente un helper di URL rails?

module ApplicationHelper 
    # [...] 

    def foo_path(foo, options = {}) 
    options.merge!(bar: foo.some_attribute) 
    super 
    end 

    # [...] 
end 

Ora, questo funziona quando viene chiamato da una vista, ma quando viene chiamato da un controller, la variante originale senza le mie aggiunte è Usato.

Come è possibile eseguire l'override dell'applicazione Helpers (_path/_url)?

risposta

3

Sembra che tu stia affrontando la strada sbagliata. È meglio aggiungere: Parametro barra nel percorso, ad esempio:

get :foo, :bar => "bar" 

In caso contrario, fornire ulteriori dettagli descrittivi sul problema.

Modifica.

Ecco la soluzione (base sul vostro aggiornamento post):

class ApplicationController < ActionController::Base 
    def foo_path(foo, options = {}) 
    options.merge!(bar: foo.some_attribute) 
    super 
    end 
    helper_method :foo_path 
end 
+0

Ho aggiornato la riga relativa per chiarire che in realtà un valore dinamico viene unito in 'options' (' foo.some_attribute'). – user569825

+0

Non funzionerà in questo modo. Quel parametro deve essere presente nell'url, altrimenti come saprebbero i binari, quale valore di: bar param dovrebbe essere. Quindi, principalmente, la risposta è 'foo_path (foo,: bar => foo.some_attribute)' che genererà url qualcosa come '/ foo /: id? Bar = some_attr_value' – intale

+0

Funziona già - solo che non è usato quando chiamato dai controller. "Sa" perché è assegnato esplicitamente il valore di "foo.some_attribute". – user569825

7

penso che il modo più pulito per raggiungere tale è quello di personalizzare routes.rb di file (almeno per i parametri di default statici). Documenti: http://guides.rubyonrails.org/routing.html#customizing-resourceful-routes

predefinito param esempio:

get "/foo(/:bar)" => "my_controller#index", defaults: { bar: "my_default" } 

predefinito esempio valore param + portata:

scope '/(:rec_type)', defaults: { rec_type: 'mammo' }, rec_type: /mammo|face/ do 
    resources :patients 
end 

Altre opzioni (per restriccions dinamici):

avanzata vincoli di instradamento:

Se sono necessarie ulteriori restrizioni avanzate/dinamiche, dare un'occhiata a questa guida: http://guides.rubyonrails.org/routing.html#advanced-constraints.

default_url_options

Override:

Inoltre, è possibile eseguire l'override default_url_options metodo per aggiungere automaticamente alcuni attributi (params) utilizzando rotte aiutanti: http://guides.rubyonrails.org/action_controller_overview.html#default-url-options.

È possibile impostare i parametri predefiniti globali per la generazione di URL definendo un metodo denominato default_url_options nel controller. Tale metodo deve restituire un hash con i valori predefiniti desiderati, le cui chiavi devono essere simboli:

class ApplicationController < ActionController::Base 
    def default_url_options(options = {}) 
    if action_name == 'foo' # or other conditions 
     options[:bar] = 'your_defaults' # add here your default attributes 
    end 

    options 
    end 
end 

Override to_param: sistema di routing

Rails chiama to_param sui modelli per ottenere un valore per il :id segnaposto. ActiveRecord::Base#to_param restituisce l'ID di un modello, ma è possibile ridefinire tale metodo nei modelli.Ad esempio, dato:

class Product < ActiveRecord::Base 
    def to_param 
    "#{id}-#{title}" 
    end 
end 

Questo genera: /products/254-Foo

+0

Ho aggiornato la riga relativa per chiarire che in realtà un valore dinamico viene unito in 'options' (' foo.some_attribute'). – user569825

2

Poiché le risposte attuali mostrano, si non abbiano la prevalenza un aiutante rotaie (come definito da qualche parte nella cartella app/helpers), ma un aiutante percorso (come definito in config/routes.rb).

Chiamare il metodo foo_path da una vista funziona, perché prima Rails esaminerà tutti i metodi di helper delle applicazioni disponibili prima di esaminare i metodi di supporto di routing disponibili.

Chiamare il metodo da un controller non funziona, perché Rails passerà solo attraverso i metodi di helper di routing disponibili, non tramite gli helper di routing.

Se si desidera chiamare un aiutante applicazione da un controller, utilizzare questo all'interno il controller:

view_context.foo_path(...) 

Ciò richiede di anteporre view_context. per ogni chiamata a foo_path all'interno di ogni controllo, quindi non è un perfetto soluzione ma dovrebbe funzionare.

+0

+1 per la spiegazione. Grazie. Forse questo dovrebbe invece dire "non attraverso gli aiutanti dei binari"? "[...] passerà solo attraverso i metodi di helper di routing disponibili, non attraverso gli helper di routing. [...]" – user569825

+0

'view_context' funziona in dev o in produzione, ma nel test, non lo fa .. – raven

3

In Rails 3 e 4, gli helper URL url risiedono tutti in questo modulo Rails.application.routes.url_helpers. Quindi possiamo includere un modulo per sovrascrivere i metodi al suo interno.

module FooUrlHelper 
    def foo_path(foo, options = {}) 
    options.merge!(bar: foo.some_attribute) 
    super 
    end 
end 

# Works at Rails 4.2.1 
Rails.application.routes.url_helpers.send(:include, FooUrlHelper) 

# For Rails 4.2.6, I thought the following worked, but there seems to be issues, don't have time to figure out a solution yet 
Rails.application.routes.named_routes.url_helpers_module.send(:include, FooUrlHelper) 

si può semplicemente inserire questo all'interno initializers

Ho provato questo in console e controller e sembra funzionare bene.

+0

Il vantaggio di questo metodo è che, a differenza dei metodi di aggiunta o aliasing in ApplicationController, funziona in tutte le posizioni che utilizzano gli helper degli URL come i modelli di mailer. –

Problemi correlati