The problem with your code is explained by Ed S.
Otherwise, you can do
products.reject! { |s| s.nil? || s.strip.empty? }
Why do you need to test nil? first? Let's check few lines.
nil.strip
# NoMethodError: undefined method `strip' for nil:NilClass
" ".strip
# => ""
Now, with a different order, what the code does if the object is a string, and then if it is nil.
" ".strip || " ".nil?
# => ""
nil.strip || nil.nil?
# NoMethodError: undefined method `strip' for nil:NilClass
# Oh you don't want that to happen, do you?
This means you don't want to call strip.empty? when your object is nil.
And as you know, when you have a || b, if a is truthy (i.e. not nil nor false), b will never be called.
You test first if the string is nil ; if it is, you don't need to check the right part (so you won't get a undefined method error) and the object will be removed from your products list.
products.reject! { |s| s.strip.empty? || s.nil? }products.reject! { |product| product.nil? || product.strip.empty? }otherwise you'll try tostripnilstriptosbefore evaluating whether or notswasnil. This should have raisedNoMethodError: undefined method 'strip' for nil:NilClass. By reversing the order, you can avoid that situation.