2011-02-25 13 views
15

con el siguiente código:¿Hay alguna manera en Rails de omitir un before_filter si la solicitud es xhr?

class TestsController < ApplicationController 
    skip_before_filter :load_something,  # how to skip these only 
        :load_something_else # if the request is xhr ? 

    def index 
    respond_to do |format| 
     format.html 
     format.js 
    end 
    end 

end 

¿Hay una manera de saltar antes de filtros, dependiendo de si la solicitud es una llamada de JavaScript sin necesidad de cambiar los métodos y :load_something:load_something_else?

Gracias!

Respuesta

18

No solía haber una solución limpia para esto. Suponiendo que no tiene control sobre before_filters (o no quiere cambiarlos), dejaría el skip_before_filter y agregaría un before_filter adicional que solo ejecuta los métodos deseados si es un método xhr.

así que algo como

skip_before_filter :load_something,  # how to skip these only 
        :load_something_else # if the request is xhr ? 
before_filter :do_loads_if_xhr 

def do_loads_if_xhr 
    if request.xhr? 
    load_something 
    load_something_else 
    end 
end 

El método descrito here sólo funciona debido a que el condicional es global para la aplicación: el condicional sólo se evalúa cuando se crea la clase. No en cada solicitud.

[ACTUALIZADO] Sin embargo, hay una manera más clara de hacer que el skip_before_filter sea condicional. Escribe así:

skip_before_filter :load_something, :load_something_else, :if => proc {|c| request.xhr?} 

También tenga en cuenta que, si bien skip_before_filter sigue siendo totalmente compatible, y no obsoleta, ya que los carriles 4 La documentación parece preferir la (idéntico) skip_before_action. Además, la documentación no es totalmente clara al respecto, tuvo que verificar en el código.

3

¿Ha codificado esos filtros? En ese caso, se puede escribir una cláusula if dentro de ellos sin necesidad de utilizar skip_before_filter:

def load_something 
    unless request.xhr? 
    #Code 
    end 
end 

En el otro lado, puede hacer yout propio filtro y delegado:

before_filter :my_own_filter 

def my_own_filter 
    unless request.xhr? 
    load_something 
    load_something_else 
    end 
end 

Creo que esto debería funcionar.

+0

¿No deberían ser los métodos && d juntos para que si uno anterior devuelve falso, entonces los otros no se ejecutarán y la cadena de filtros se detendrá? –

4

Utilice alias_method_chain para decorar los filtros, por lo que no se ejecutarán si la solicitud es xhr.

def load_something_with_noxhr(*args) 
    load_something_without_noxhr(*args) unless request.xhr? 
end 

alias_method_chain :load_something, :noxhr 

(cambiar load_something en lo que sea necesario, el _with_ y _without_ son literales, y el sufijo noxhr debe ser el mismo pasa como segundo argumento en la llamada alias_method_chain.)

+0

Parece que 'alias_method_chain' podría estar en desuso/no se recomienda http://stackoverflow.com/questions/3689736/rails-3-alias-method-chain-still-used – colllin

+1

No es que no se lo recomiende, pero ahora (Ruby 2.1) está el marvellos 'prepend MyModule' que pone su módulo _en frente_ de la cadena de llamadas, por lo que la función en el módulo puede llamar a' super' y llamar a la función con el mismo nombre en la clase "incluida". – rewritten

37

Pruebe esta línea para omitir la filtrado por una condición:

skip_before_filter :load_something, :load_something_else, 
    :if => proc { request.xhr? } 

Para también se puede utilizar lambdas (que tienen un rigor en el paso de argumentos):

skip_before_filter :load_something, :load_something_else, 
    if: -> { request.xhr? } 

o con un argumento:

skip_before_filter :load_something, :load_something_else, 
    if: ->(arg) { request.xhr? && arg } 
9

Todas estas respuestas toman el camino equivocado en mi opinión.Usar skip_before_action con una condición es hacerlo hacia atrás, y no es tan explícito y claro como agregar la condición a la acción anterior; así que esta es mi propuesta:

before_action :require_password_change, unless: -> { request.xhr? } 

De esta manera, a alguien leyendo su código es claro en qué condiciones before_action carreras o no se ejecuta, sin tener que depender de que éstos se produzcan a través de este skip_before_action en algún lugar del controlador jerarquía.

+0

este es el mejor enfoque que he visto –

Cuestiones relacionadas