Joshua Pinter
Joshua Pinter

Reputation: 47611

Clean way of checking for a "nil" String

I have a scenario where I'm specifically looking for a String with the value of "nil". In short, I have a conditional where I want to pass nil if the user selects that option in the dropdown and not pass "nil", which is what gets passed in the params:

My Select:

<select name="parent_id"> 
  <option name="All">All</option>
  <option name="None" value="nil">None</option>
</select>

My condition:

if params[ :parent_id ].present?
  Child.where( parent_id: params[ :parent_id ] ) # I want this to be IS NULL when params[ :parent_id ] == "nil"
end

Typically, you would use .nil? or .blank? on a String to check for a nil value or an empty String. But "nil".nil? and "nil".blank? both equal false, as they should.

So I'm curious if there's a good way to check for a String being "nil".

Currently I'm using myString == "nil" but that leads to things like ( myString == "nil" ? nil : myString ).

if params[ :parent_id ].present?
  parent_id = params[ :parent_id ] == "nil" ? nil : params[ :parent_id ]
  Child.where( parent_id: parent_id )
end

That's fine when it's used once in a while but if this is being used frequently, it's not ideal.

This a fairly rare occurrence, I know, but it was particularly difficult to Google so I thought I would ask SO.

My initial thoughts are:

Upvotes: 3

Views: 553

Answers (2)

engineersmnky
engineersmnky

Reputation: 29598

This is how I would go about it

class Child 
  belongs_to :parent 

  scope :by_parent, ->(parent_id=nil) { 
    parent_id.to_i == 0 ? without_parent : where(parent_id: parent_id.to_i)
  }
  scope :without_parent, -> { where(parent_id: nil) } 
end 

then your controller code is simply

 Child.by_parent(params[:parent_id])

Upvotes: 0

mrzasa
mrzasa

Reputation: 23347

I'd suggest to change the select to:

  <option name="None" value="">None</option>

If you can't do it - I'd refrain from monkey patching.

You can add "nil" checking to conditions:

if params[ :parent_id ].present? && params[ :parent_id != 'nil' 
  Child.where(parent_id: params[:parent_id]))
end

or you can filter the params in a separate method:

def filtered_params
  @filtered_params |= params.tap{|p| p[:parent_id] = nil if p[:parent_id] == 'nil' }
end

and use filtered_params instead of params in your controller code.

Upvotes: 1

Related Questions