Search code examples
ruby-on-railsrubyruby-on-rails-4

Ruby - Next if vs Next unless


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

Solution

  • 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.