What is the difference between next if
vs next unless
.
My understanding of next if
was that next only if variable == value
but in the following code, the second next statement isn't working. next if datastore.id == 5
it is bypassing this and proceeding even if the datastore.id == 2
or datastore.id == 3
etc.,
$evm.vmdb(:ManageIQ_Providers_Vmware_InfraManager_Storage).all.each do |datastore|
next if datastore.ems_id == provider.id.to_s
next if datastore.id == 5
dialog_hash[datastore[:id]] = "#{datastore.name} on #{datastore.ext_management_system.name}"
end
But if I change the next if
to next unless
then it works fine.
$evm.vmdb(:ManageIQ_Providers_Vmware_InfraManager_Storage).all.each do |datastore|
next if datastore.ems_id == provider.id.to_s # Next if works here
next unless datastore.id == 5 # Next unless works here instead of next if
dialog_hash[datastore[:id]] = "#{datastore.name} on #{datastore.ext_management_system.name}"
end
CodePudding user response:
The difference is that
next if condition
callsnext
when thecondition
istrue
, butnext unless condition
callsnext
when thecondition
isfalse
.
When calling next
with a condition like datastore.id == 5
doesn't work as expected, then the problem is not the usage of if
or unless
because they work the opposite way.
Instead, you need to debug why you expect datastore.id == 5
to be true
and why it is not. Obviously, the condition datastore.id == 5
can only be true
when datastore.id
returns the integer 5
. If it returns false
then datastore.id
might return a string with the digit "5"
.
I suggest adding debug output to your code to dig deeper, like this:
p datastore.id
p datastore.id.class
CodePudding user response:
I'll quickly explain next
and the difference between if
and unless
in ruby, and proceed to suggest some things you could try to get your code to work.
if
Code would execute if the condition is true.
unless
Code would execute if the condition is false. It would work the same as:
if !(expression) { ... }
next
The program would skip the rest of the code inside the loop block, and skip to the next iteration.
In your case, if there is a next
called in the first line, then the rest of the code wouldn't run.
$evm.vmdb(:ManageIQ_Providers_Vmware_InfraManager_Storage).all.each do |datastore|
next if datastore.ems_id == provider.id.to_s # if this condition is true, don't run rest of the code in this loop, and go to the next datastore
next if datastore.id == 5
dialog_hash[datastore[:id]] = "#{datastore.name} on #{datastore.ext_management_system.name}"
end
Suggestion
It's unclear from your question what you mean by if
doesn't work but unless
does.
From the first code snippet in the question, the last line of the code. i.e,
dialog_hash[datastore[:id]] = "#{datastore.name} on #{datastore.ext_management_system.name}"
would only run if both of the conditions above are false
.
You can check where the data is unexpected, or if your initial conditions are wrong, by debugging the datastore
with either a debugger or some puts
statements inside the loop.
All the best.