Como testar se existem parâmetros nos trilhos

179

Estou usando uma instrução IF no Ruby on Rails para tentar testar se os parâmetros de solicitação estão definidos. Independentemente de os dois parâmetros serem definidos ou não, a primeira parte do seguinte se o bloco for acionado. Como posso fazer com que esta peça seja acionada SOMENTE se os parâmetros [: um] e [: dois] estão definidos?

if (defined? params[:one]) && (defined? params[:two])
 ... do something ...
elsif (defined? params[:one])
 ... do something ...
end
Darren
fonte
10
@ Nakilon: Dado que paramsé um método do controlador Rails (que retorna um HashWithIndifferentAccess), trata-se de Rails.
mu é muito curto

Respostas:

348

Você quer has_key?:

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

Apenas verificar if(params[:one])será enganado por um valor "lá, mas nulo" e "lá, mas falso", e você está perguntando sobre a existência. Pode ser necessário diferenciar:

  • Nem aí.
  • Lá mas nil .
  • Lá mas false .
  • Lá, mas uma string vazia.

também. Difícil dizer sem mais detalhes da sua situação precisa.

mu é muito curto
fonte
3
@sawa Não é possível passar um nilparâmetro. Se o parâmetro existir, será uma sequência vazia.
Jacob Relkin
5
@ Jacob: Não há garantia de que paramsnão tenha sido pré-processado antes de chegarmos aonde estamos verificando o que está nele. Daí a minha lista de possíveis casos especiais para verificar. Melhor dizer exatamente o que você quer dizer com IMHO.
mu é muito curta
1
@muistooshort meu mal, que era Python :(
FloatingRock
2
No Rails 5, o objeto params não é mais um hash e não vejo o key?método. edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson
1
@muistooshort Oh, bom. Ainda estou um pouco hesitante em usar métodos que não fazem parte da API documentada, mas tenho certeza de que é seguro o suficiente. Estou ligando params.to_h.key?agora.
stephen.hanson
86

Eu sou fã de

params[:one].present?

Só porque ele mantém o params[sym]formulário e fica mais fácil de ler.

netricar
fonte
1
Melhor, 3 caracteres mais curtos, mais simples.
Bengala
este deve ser a melhor resposta válida!
jacktrade
4
Cuidado usando presente? com booleanos (método indefinido `presente 'para true: TrueClass). A resposta aceita com has_key? funciona para todos os tipos.
StCleezy
2
Para deixar claro, isso não funciona em alguns casos como, por exemplo, false.present? => false Portanto, não funcionará quando, por exemplo, passar parâmetros via json body, como pode passar booleanos.
James
1
se você estiver usando essa lógica em uma exibição, o presente falhará, pois a matriz de parâmetros já está sendo invocada e falhará se for nula. has_keyem vez disso, fornece o que você está procurando.
Jerome
22

usar em branco? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

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

retornará true se estiver vazio ou nulo

Também ... isso não funcionará se você estiver testando valores booleanos.

>> false.blank?
=> true

Nesse caso, você poderia usar

unless params[:one].to_s.blank? && params[:two].to_s.blank?
Orlando
fonte
3
Ou present?que retorna o oposto de blank?. Então você pode transformar isso unlessem um, ifse quiser.
quer
@ Inking que funciona, mas um inline unlessestá ok. Mas sim, eu gosto mais ifcompresent?
Orlando
18

Você pode escrevê-lo de forma mais sucinta como o seguinte:

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
fonte
1
Eu gosto de como isso é limpo. Eu sou novo no Ruby. Quaisquer armadilhas ou casos extremos que eu deva conhecer?
Sean
10

Simples como torta:

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
fonte
3
Isso não verifica se o parâmetro está lá, mas na verdade está definido como nulo.
Daemin
@Daemin Na realidade, porém, um parâmetro não pode ser definido como nulo no cabeçalho de uma solicitação. É nulo ou uma corda.
Jacob Relkin
Sim, mas como outras pessoas declararam, ele pode ser modificado por outra coisa, um plug-in, uma jóia ou seu próprio código, ou simplesmente falha na análise por algum motivo bizarro.
Daemin
4
Fazendo uma torta é realmente complicado
Cesar
por que você não usa a menos que
Alireza Rahmani Khalili
5
if params[:one] && params[:two]
 ... do something ...
elsif params[:one]
 ... do something ...
end
fl00r
fonte
5

Uma maneira muito simples de fornecer valores padrão para seus parâmetros: params[:foo] ||= 'default value'

chrpes
fonte
2
você poderia fazer params.fetch(:foo, 'default value')muito
Mario Pérez
5

Acabei de ler isso nas classes RubyInRails http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

você pode usar blank? método equivalente aparams[:one].nil? || params[:one].empty?

(por exemplo)

if params[:one].blank? 
  # do something if not exist
else
  # do something if exist
end
Basil Mariano
fonte
Perfeito, eu estava usandoparams[:one].nil? || params[:one].empty?
GOXR3PLUS
Se key é o método certo, seu método supõe que esse parâmetro já exista, então você está validando nil nil, o que poderia funcionar, mas não o melhor método.
Paul Brunache 19/03/19
3

Você também pode fazer o seguinte:

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

Costumo usar a solução acima quando quiser verificar mais de um ou dois parâmetros.

.values_at retorna e matriz com zero no lugar de qualquer chave param indefinida. ou seja:

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

retornará o seguinte:

[3,nil,5] 

.includes? (nil), em seguida, verifica se há valores nulos na matriz. Retornará true se o array incluir nulo.

Em alguns casos, você também pode querer verificar se os parâmetros não contêm e esvaziam a string com valor falso.

Você pode manipular esses valores adicionando o código a seguir acima da instrução salvo.

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

todos juntos ficaria assim:

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

É importante observar que delete_if modificará seus hash / parâmetros, portanto, use com cuidado.

A solução acima claramente requer um pouco mais de trabalho para configurar, mas vale a pena se você estiver verificando mais do que apenas um ou dois parâmetros.

Greg L
fonte
3

Além das respostas anteriores: has_key?e has_value?tenha alternativas mais curtas na forma de key?e value?. A equipe Ruby também sugere o uso de alternativas mais curtas, mas para facilitar a leitura alguns ainda podem preferir versões mais longas desses métodos.

Portanto, no seu caso, seria algo como

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

NB! .key?apenas verificará se a chave existe e ignora o valor possível. Por exemplo:

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
fonte
2

Aqui está o que eu faço,

before_action :validate_presence

e depois os seguintes 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
fonte
1

Apenas reuni-lo para o mesmo 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

a primeira linha verifica se nossas chaves de destino estão presentes nas chaves dos parâmetros usando o subconjunto <=? operador. Enumerable.all? sem bloco por padrão retornará falso se algum valor for nulo ou falso.

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

Você também pode verificar se os parâmetros estão vazios usando os parâmetros [: two] .empty

Jason Yost
fonte
1
Enquanto isso cobre o caso em que os dois parâmetros são definidos. Não cobre o caso em que um deles é avaliado como falso.
EMFI
0

Eu tento um atraso, mas de longe vista resposta:

Se você deseja saber se os valores em um (qualquer) hash estão definidos, tudo acima responde como verdadeiro, dependendo do ponto de vista deles.

Se você quiser testar seus parâmetros (GET / POST ..), use algo mais especial para o que você espera que seja o valor params[:one], algo como

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

ignorando o parâmetro (GET / POST) como se eles não estivessem definidos, se não se ajustassem como esperado

apenas uma if params[:one] detecção com ou sem nula / verdadeira é um passo para abrir sua página para hackers, porque normalmente é o próximo passo para usar algo comoselect ... where params[:one] ... , se isso é intencional ou não, ativo ou dentro ou após uma estrutura.

uma resposta ou apenas uma dica

halfbit
fonte