2011-03-31 8 views
75

Tengo un método que hace algo como esto:before_filter con parámetros

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

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

También quiero utilizar este método en algunos otros controladores, así que copié el método a un ayudante que se incluye en el application_controller.

el problema es que, en algunos controladores, la identificación para el proyecto no es el símbolo :id sino f.e. :project_id (y también un :id está presente (por otro modelo)

¿Cómo resolver este problema? ¿Existe una opción para añadir un parámetro a la acción before_filter (para pasar el parámetro derecha)?

Respuesta

78

lo haría así:.

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 

Dónde correct_id_here es el id correspondiente para acceder a una Project.

+2

¿hay alguna manera de agregar un símbolo ',: only => [: show]'? Tengo un error al intentar 'before_filter {| c | c.authenticate_rights correct_id_here},: only => [: show] ' – choise

+23

Probar al revés:' before_filter (: only => [: show]) {} '. Más ejemplos aquí: http://apidock.com/rails/ActionController/Filters/ClassMethods/before_filter – fguillen

+1

Si asegura esto haciendo que el 'before_filter' sea un método privado, entonces quizás vuelva a factorizarlo (por ejemplo, muévalo a un controlador principal, ApplicationController, etc.), necesitará usar 'c.send (: filter_name, ...)' ya que el filtro no se ejecutará en el contexto del controlador. http://guides.rubyonrails.org/action_controller_overview.html#other-ways-to-use-filters –

-1

Esto debería trabajo:

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

esto debería devolver params[:project_id] si está presente en el hash params, o volver params[:id] si no es

+0

el problema es que a veces ambos están presentes (anidados) y encuentra un proyecto que no es el correcto. – choise

+0

@choise: Eso no debería suceder: si 'project_id' está presente, la cláusula' o' se asegurará de que esto se use; solo si no se suministra 'project_id' se seleccionará el parámetro' id'.En otras palabras: cuando se suministran ambos parámetros, la cláusula 'o' asegura que se use el valor correcto, ya que siempre preferirá' project_id'. Naturalmente, no desearía llamar a este método cuando ninguno está presente, o cuando no hay 'project_id' pero hay un' id' que no hace referencia a un proyecto. –

13

Continuar respuesta @alex', si quieres :except o :only algunos métodos, aquí se muestra la sintaxis:

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

Encontrado here.

58

Con un poco de azúcar sintáctica:

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

O si usted decide obtener aún más elegante:

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

Y puesto que los carriles 4 before_action, sinónimo de before_filter, se introdujo, por lo que puede escribirse como:

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

NB

-> representa lambda, llamados lambda literal, introducir en Ruby 1.9

%i creará una serie de símbolos

+4

Esta respuesta es más elegante porque la lambda se predetermina al contexto de ejecución de la clase, por lo tanto, se pueden llamar a métodos privados sin usar '.send' –

+0

@Vadym Tyemirov ¿'find_campaign' es el nombre del método privado? En 'param = params [: id]', ¿'param' es el nombre de la nueva variable local que se pasará como argumento a' find_campaign'? Es decir, que dentro del método privado 'find_campaign' en sí, usamos' param' not, 'params {: id]'? – ahnbizcad

+0

'find_campaign' podría ser cualquiera, pero lo haría de forma privada para asegurarme de no exponer lo que no se consume. 'params' es una variable hash disponible para nuestros métodos,' param' es cualquier variable que deba pasar al método find_campaign, p. 'before_action -> (campaign_id = params [: id]) {find_campaign (campaign_id)}, solo:% i | show edit update destroy | ' –

3

encuentro el método de bloques que se utilizan llaves en lugar de do...end ser la más clara opción

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

before_action es sólo el más reciente preferido Synta x para before_filter

+0

genial! gracias por esta actualización – choise