Cómo probar si existen parámetros en rieles

179

Estoy usando una declaración IF en Ruby on Rails para probar y probar si los parámetros de solicitud están establecidos. Independientemente de si ambos parámetros están configurados o no, la primera parte de lo siguiente si se activa el bloque. ¿Cómo puedo hacer que esta parte SOLO se active si ambos parámetros [: uno] y parámetros [: dos] están configurados?

if (defined? params[:one]) && (defined? params[:two])
 ... do something ...
elsif (defined? params[:one])
 ... do something ...
end
Darren
fuente
10
@Nakilon: Dado que paramses un método de controlador Rails (que resulta que devuelve un HashWithIndifferentAccess), se trata de Rails.
mu es demasiado corto el

Respuestas:

348

Tu quieres has_key?:

if(params.has_key?(:one) && params.has_key?(:two))

Solo la comprobación se if(params[:one])dejará engañar por un valor "allí pero nulo" y "allí pero falso" y se preguntará acerca de la existencia. Es posible que deba diferenciar:

  • No hay nada en absoluto.
  • Ahí pero nil.
  • Ahí pero false.
  • Hay pero una cadena vacía.

también. Difícil de decir sin más detalles de su situación precisa.

mu es demasiado corto
fuente
3
@sawa No es posible pasar un nilparámetro. Si el parámetro existe, será una cadena vacía.
Jacob Relkin el
55
@Jacob: No hay garantía de que paramsno haya sido preprocesado antes de llegar a donde estamos revisando lo que contiene. De ahí mi lista de posibles casos especiales para verificar. Lo mejor es decir exactamente lo que quieres decir en mi humilde opinión.
mu es demasiado corto el
1
@muistooshort mi mal, eso fue Python :(
FloatingRock
2
En Rails 5, el objeto params ya no es un hash, y no veo el key?método. edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson
1
@muistooshort Oh, bien. Todavía dudo un poco en utilizar métodos que no forman parte de la API documentada, pero estoy seguro de que es lo suficientemente seguro. He estado llamando params.to_h.key?por ahora.
stephen.hanson
86

soy un fan de

params[:one].present?

Solo porque mantiene el params[sym]formulario para que sea más fácil de leer.

netricate
fuente
1
Mejor, 3 caracteres más cortos, más simples.
Bengala
¡Esta debería ser la mejor respuesta válida!
jacktrade
44
Cuidado con el presente? con booleanos (método indefinido 'presente' para verdadero: TrueClass). La respuesta aceptada con has_key? Funciona para todo tipo.
StCleezy
2
Para que quede claro, esto no funciona en algunos casos como, por ejemplo, false.present? => falso Así que no funcionará cuando, por ejemplo, pase parámetros a través del cuerpo json como puede pasar booleanos
James
1
si está utilizando esta lógica en una vista, present fallará ya que la matriz de parámetros ya se invoca y falla si es nula. has_keyen cambio te da lo que estás buscando.
Jerome el
22

utilizar en blanco? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

unless params[:one].blank? && params[:two].blank?

devolverá verdadero si está vacío o nulo

también ... eso no funcionará si está probando valores booleanos ... ya que

>> false.blank?
=> true

en ese caso podrías usar

unless params[:one].to_s.blank? && params[:two].to_s.blank?
Orlando
fuente
3
O present?que devuelve lo contrario de blank?. Entonces podrías convertir eso unlessen un ifsi quisieras.
Inkling
@Inkling que funciona, pero en línea unlessestá bien. Pero sí, me gusta más ifconpresent?
Orlando
18

Puede escribirlo más sucintamente de la siguiente manera:

required = [:one, :two, :three]
if required.all? {|k| params.has_key? k}
  # here you know params has all the keys defined in required array
else
  ...
end
Zack Xu
fuente
1
Me gusta lo limpio que es esto. Aunque soy nuevo en Ruby. ¿Algún inconveniente o caso de borde perdido que debería saber?
Sean
10

Simple como pastel:

if !params[:one].nil? and !params[:two].nil?
  #do something...
elsif !params[:one].nil?
  #do something else...
elsif !params[:two].nil?
  #do something extraordinary...
end
Jacob Relkin
fuente
3
Eso no comprueba si el parámetro está allí, sino que se establece en nulo.
Daemin
@Daemin Sin embargo, en realidad, un parámetro no se puede establecer en nulo en un encabezado de solicitud. Es nulo o una cadena.
Jacob Relkin el
Sí, pero como han dicho otras personas, podría modificarse por otra cosa, un complemento, una gema o su propio código, o simplemente no se analiza por alguna extraña razón.
Daemin
44
Hacer un pastel es realmente complicado
Cesar
¿Por qué no lo usas a menos que?
Alireza Rahmani Khalili
5
if params[:one] && params[:two]
 ... do something ...
elsif params[:one]
 ... do something ...
end
fl00r
fuente
5

Una forma muy simple de proporcionar valores predeterminados a sus parámetros: params[:foo] ||= 'default value'

chrpes
fuente
2
que podría hacer params.fetch(:foo, 'default value')demasiado
Mario Pérez
5

Acabo de leer esto en las clases de RubyInRails http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

puedes usar un blank?método equivalente aparams[:one].nil? || params[:one].empty?

(p.ej)

if params[:one].blank? 
  # do something if not exist
else
  # do something if exist
end
Albahaca mariano
fuente
Perfecto, estaba usandoparams[:one].nil? || params[:one].empty?
GOXR3PLUS
has key es el método correcto, tu método asumió que este parámetro ya existe, por lo que estás validando nil on nil, lo que podría funcionar pero no es el mejor método.
Paul Brunache
3

También puedes hacer lo siguiente:

unless params.values_at(:one, :two, :three, :four).includes?(nil)
 ... excute code ..
end 

Tiendo a usar la solución anterior cuando quiero verificar más de uno o dos parámetros.

.values_at devuelve y matriz con nil en lugar de cualquier clave de parámetro indefinida. es decir:

some_hash = {x:3, y:5}
some_hash.values_at(:x, :random, :y}

devolverá lo siguiente:

[3,nil,5] 

.incluye? (nil) luego verifica la matriz para cualquier valor nulo. Volverá verdadero si la matriz incluye nil.

En algunos casos, es posible que también desee comprobar que los parámetros no contienen una cadena vacía en un valor falso.

Puede manejar esos valores agregando el siguiente código encima de la declaración a menos que.

params.delete_if{|key,value| value.blank?}

todos juntos se vería así:

 params.delete_if{|key,value| value.blank?}
 unless params.values_at(:one, :two, :three, :four).includes?(nil)
   ... excute code ..
  end

Es importante tener en cuenta que delete_if modificará sus hash / params, así que úselo con precaución.

La solución anterior claramente requiere un poco más de trabajo para configurar, pero vale la pena si está comprobando más de uno o dos parámetros.

Greg L
fuente
3

Además de las respuestas anteriores: has_key?y has_value?tienen alternativas más cortas en forma de key?y value?. El equipo de Ruby también sugiere usar alternativas más cortas, pero para facilitar la lectura, algunos podrían preferir versiones más largas de estos métodos.

Por lo tanto, en su caso sería algo así como

if params.key?(:one) && params.key?(:two)
  ... do something ...
elsif params.key?(:one)
  ... do something ...
end

¡NÓTESE BIEN! .key?solo verificará si la clave existe e ignora el valor posible. Por ej .:

2.3.3 :016 > a = {first: 1, second: nil, third: ''}
  => {:first=>1, :second=>nil, :third=>""}
2.3.3 :017 > puts "#{a.key?(:first)}, #{a.key?(:second)}, #{a.key?(:third), #{a.key?(:fourth)}}"
true, true, true, false
Andres Ehrenpreis
fuente
2

Esto es lo que hago

before_action :validate_presence

y luego los siguientes métodos:

    def check_presence
  params[:param1].present? && params[:param2].present?
 end

 def validate_presence
  if !check_presence
    render json:  {
                      error:  {
                                message: "Bad Request, parameters missing.",
                                status: 500
                              }
                    }
  end
 end
Parth Modi
fuente
1

Solo reconstruí esto para el mismo problema:

before_filter :validate_params

private

def validate_params
  return head :bad_request unless params_present?
end

def params_present?  
  Set.new(%w(one two three)) <= (Set.new(params.keys)) &&
  params.values.all?
end

la primera línea verifica si nuestras claves de destino están presentes en las claves de los parámetros usando el subconjunto <=? operador. Enumerable.todos? sin bloqueo por defecto devuelve falso si algún valor es nulo o falso.

okthatsneat
fuente
0
if params[:one] && param[:two]
  ... excute code ..
end

También puede verificar si los parámetros están vacíos usando params [: two] .empty

Jason Yost
fuente
1
Si bien esto cubre el caso donde ambos parámetros están definidos. No cubre el caso en que uno de ellos se evalúa como falso.
EmFi
0

Intento una respuesta tardía, pero a la vista:

Si desea saber si los valores en un hash (cualquiera) están establecidos, todo lo anterior responde a un verdadero, dependiendo de su punto de vista.

Si desea probar sus parámetros (GET / POST ..), debe usar algo más especial de lo que espera que sea el valor params[:one], algo como

if params[:one]~=/   / and  params[:two]~=/[a-z]xy/

ignorando el parámetro (GET / POST) como si no estuvieran configurados, si no encajan como se esperaba

solo una if params[:one] detección con o sin detección nula / verdadera es un paso para abrir su página para hackear, porque, por lo general, es el siguiente paso para usar algo como select ... where params[:one] ..., si es intencionado o no, activo o dentro o después de un marco.

una respuesta o solo una pista

medio bit
fuente