-1

My goal is to fill an html table in a view (schedule.html.haml):

 - if @plans != nil
   %p display this if plans is not null
 - if @plans == nil
   %p= action_name

with the data from @plans in a controller:

def schedule
 @plans = Order.all
end

I am sure Order.all returns data. Route file is:

get 'schedule', to: 'order_articles#schedule'

When I try to do this plans is null. The output is:

schedule

I tried to check if plans is null with the code in the view. What did I do wrong?

sawa
  • 165,429
  • 45
  • 277
  • 381
F. LK
  • 75
  • 1
  • 10
  • 1
    Please provide a [mcve]. What is the route and controller action? How are you calling it? What is being rendered? Your code snippet does not provide enough information for anyone to help. – Tom Lord Apr 03 '18 at 09:17
  • Nothing in your above code indicates that `@plans` would be `nil`. It should always be a (potentially empty) array. So there must be *something* wrong with how you're calling the controller action/setting the variable, but I don't know what. – Tom Lord Apr 03 '18 at 09:20
  • 1
    @Elyasin That won't make a difference. `nil` is the singleton instance of `NilClass`; checking `#nil?` is exactly the same thing as checking `== nil`. – Tom Lord Apr 03 '18 at 09:21
  • @F. LK, I don't think it will be effective evaluating using `nil`, see my answer below explained how. – oj5th Apr 03 '18 at 09:44

2 Answers2

1

Ruby has a stricter and more sane type coercion scheme than other popular dynamic languages:

irb(main):001:0> !!nil
=> false
irb(main):002:0> !![]
=> true
irb(main):003:0> !!""
(irb):3: warning: string literal in condition
=> true
irb(main):004:0> !!0
=> true

Everything except nil and false evaluate to true. nil is only equal to nil.

Order.all will never return nil, if no records are found it returns an empty ActiveRecord::Collection object. It's an array like result object telling you there was nothing in the database.

So when dealing with collections you need to use the appropriate methods such as .any?, .none? etc:

- if @plans.any?
   %p display this if there are any plans.
- else
   %p= action_name
max
  • 96,212
  • 14
  • 104
  • 165
0

You should use present?, any? or none? instead of nil?.

If you evaluate with nil?, it will always return false because it always return empty array [] if the object does not have any record.

For example:

Your Order table doesn't have any record.

=> @plans = Order.all
=> @plans.nil?
=> false

=> @plans
=> []

And if it has any record?

=> @plans = Order.all
=> @plans.nil?
=> false

=> @plans
=> [#<Order:0x007fa2832c0308
 id: 1,
 your_field: 'value'>]

Suggestion #1

View (schedule.html.haml):

- if @plans.present?
  %p display this if plans is not null
- else
  %p= action_name

Suggestion #2

View (schedule.html.haml):

- if @plans.any?
  %p display this if plans is not null
- else
  %p= action_name

Suggestion #3

View (schedule.html.haml):

- if @plans.none?
  %p= action_name
- else
  %p display this if plans is not null
oj5th
  • 1,379
  • 10
  • 25
  • I would say `any?` or `none?` reads much better. `.present?` is really for checking if the value/key is set and is not a blank value. – max Apr 03 '18 at 10:43