Ruby: Nils in an IF statement [duplicate]
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.
精彩评论