开发者

Ruby: Nils in an IF statement [duplicate]

This question already has answers here: How to avoid NoMethodEr开发者_如何学Pythonror for missing elements in nested hashes, without repeated nil checks? (16 answers) Closed 7 years ago.

I have the following very ugly ruby code in a rails app I'm working on:

if params.present?
  if params[:search].present?
    if params[:search][:tags_name_in].present?
      ...
    end
  end
end

All I'm trying to ask is whether params[:search][:tags_name_in] has been defined, but because params, and params[:search], and params[:search][:tags_name_in] might all be nil, if I use...

if params[:search][:tags_name_in].present?

... I get an error if there are no params or no search params.

Surely there must be a better way to do this... suggestions??


if you are just trying to see if its defined why not keep it simple and use the defined? function?

if defined?(params[:search][:tags_name_in])


Params will always be defined, so you can remove that.

To reduce the amount of code you can do

if params[:search] && params[:search][:tags_name_in]
  #code
end

If params[:search] is not defined, the condition will short circuit and return nil.


You can use andand for this. It handles this exact situation:

if params[:search].andand[:tags_name_in].andand.present?


You have many choices that will return the value of params[:search][:tags_name_in] or nil if params[:search] is nil.

Clear but lengthy:

params[:search] && params[:search][:tags_name_in]

Using try (from active_support):

params[:search].try(:[], :tags_name_in)

Using rescue:

params[:search][:tags_name_in] rescue nil

Using fetch:

params.fetch(:search, {})[:tags_name_in]

Note that fetch can sometime be used to avoid the if altogether, in particular if there is nothing to do when the param is not specified:

def deal_with_tags
  MyModel.where :tags => params.fetch(:search){ return }[:tags_name_in]
end


Haha, if you want to be terrible and monkeypatch nil:

class NilClass
  def [](key)
    nil
  end
end

I would recommend a short-circuited if like the other answers suggest, though.


I usually end up doing something like this:

if params.has_key?(:search) && params[:search].has_key?(:tags_name_in)
...

end

Although if you don't mind testing against nils in your if statement you could also do this:

if params[:search] && params[:search][:tags_name_in] ...

This will not throw an error because ruby short-circuits the && operator.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜