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 conditioncallsnextwhen theconditionistrue, butnext unless conditioncallsnextwhen theconditionisfalse.
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.
