Home > Back-end >  Ruby - Next if vs Next unless
Ruby - Next if vs Next unless

Time:01-15

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 calls next when the condition is true, but
  • next unless condition calls next when the condition is false.

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.

  • Related