before_filter con parametri


84

Ho un metodo che fa qualcosa del genere:

before_filter :authenticate_rights, :only => [:show]

def authenticate_rights
  project = Project.find(params[:id])
  redirect_to signin_path unless project.hidden
end

Voglio anche usare questo metodo in alcuni altri controller, quindi ho copiato il metodo su un helper incluso in application_controller.

il problema è che in alcuni controller l'id del progetto non è il :idsimbolo ma fe :project_id(ed :idè presente anche a (per un altro modello)

Come risolveresti questo problema? c'è un'opzione per aggiungere un parametro all'azione before_filter (per passare il parametro giusto)?

Risposte:


86

Lo farei così:

before_filter { |c| c.authenticate_rights correct_id_here }

def authenticate_rights(project_id)
  project = Project.find(project_id)
  redirect_to signin_path unless project.hidden
end

Dov'è correct_id_herel'ID pertinente per accedere a un file Project.


2
c'è un modo per aggiungere un ,:only => [:show]simbolo? ricevo un errore durante il tentativobefore_filter { |c| c.authenticate_rights correct_id_here }, :only => [:show]
scegli

27
Provate il contrario: before_filter(:only => [:show]) { <block_code_here> }. Altri esempi qui: apidock.com/rails/ActionController/Filters/ClassMethods/…
fguillen

1
Se lo metti in sicurezza rendendo il before_filtermetodo privato, quindi forse ri-fattorizza (ad esempio spostalo su un controller principale, ApplicationController, ecc.), Dovrai usare c.send(:filter_name, ...)poiché il filtro non verrà eseguito nel contesto del controller. guide.rubyonrails.org/…
Richard Michael

2
In questo modo, il before_filter non può essere sovrascritto / ignorato a causa della mancanza di un nome (proc). I valori che voglio trasmettere sono a livello di classe. È possibile?
oreoshake

1
@oreoshake: ho lo stesso problema. Hai trovato una soluzione?
marcus3006

67

Con un po 'di zucchero sintattico:

before_filter -> { find_campaign params[:id] }, only: [:show, :edit, :update, :destroy]

O se decidi di essere ancora più stravagante:

before_filter ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|

E poiché Rails 4 before_action, un sinonimo di before_filter, è stato introdotto, può essere scritto come:

before_action ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|

NB

->sta per lambda, chiamato lambda letterale , introdotto in Ruby 1.9

%i creerà una serie di simboli


5
Questa risposta è più elegante perché il lambda utilizza per impostazione predefinita il contesto di esecuzione della classe, quindi i metodi privati ​​possono essere chiamati senza utilizzare '.send'
David Pelaez,

@Vadym Tyemirov È find_campaignil nome del metodo privato? Inparam=params[:id] , è paramil nome della nuova variabile locale che verrà passata come argomento a find_campaign? Significato, che all'interno del find_campaignmetodo privato in sé, usiamo paramno, params{:id]?
ahnbizcad

1
find_campaign potrebbe esserlo, ma lo renderei privato per essere sicuro di non esporre ciò che non viene consumato. paramsè una variabile hash disponibile per i nostri metodi, paramè qualsiasi variabile che dovresti passare al metodo find_campaign, ad esempiobefore_action ->(campaign_id=params[:id]) { find_campaign(campaign_id) }, only: %i| show edit update destroy |
Vadym Tyemirov

14

Per continuare la risposta di @alex, se lo desideri :excepto :onlyalcuni metodi, ecco la sintassi:

before_filter :only => [:edit, :update, :destroy] do |c| c.authenticate_rights params[:id] end 

Trovato qui .


5

Trovo che il metodo del blocco utilizzando le parentesi graffe invece di do...endessere l'opzione più chiara

before_action(only: [:show]) { authenticate_rights(id) }

before_action è solo la sintassi preferita più recente per before_filter


-1

Questo dovrebbe funzionare:

project = Project.find(params[:project_id] || params[:id])

Questo dovrebbe restituire params[:project_id]se è presente nell'hash params, o restituire params[:id]se non lo è.


il problema è che a volte sono presenti entrambi (annidati) e trova un progetto che non è quello giusto.
scelta

@choise: Questo non dovrebbe accadere: se project_idè presente la orclausola garantirà che venga utilizzato - solo se project_idnon viene fornito il idparametro verrà selezionato. In altre parole: quando vengono forniti entrambi i parametri, la orclausola garantisce che venga utilizzato il valore corretto, come preferirà sempre project_id. Naturalmente, non vorrai chiamare questo metodo quando nessuno dei due è presente, o quando non c'è project_idma c'è un idche non fa riferimento a un progetto.
Ola Tuvesson
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.