qaminded
qaminded

Reputation: 13

How do I write a conditional Ruby case statement with parameters passed into the case?

I'm trying to figure out a way for a case statement to take into account two parameters passed in from a regex.

My regex example is:

When (/^(?:a|an|the) (RoleA|RoleB) attempts to access a (New|Updated) Record$/) do |role_type, record_type|.

I have a case statement that only accounts for role type right now, but how do I also have the case portion account for role_type and record_type?

My goal is to test that Role A is directed to a different set of endpoints when the record type is "New" or "Updated" and I want Role B to be directed to another set of endpoints when passing in "New" and "Updated". If they were being passed into the same endpoints, then a case statement for record_type only would suffice.

What I have right now is:

case record_type
   when 'New'
     <do something>
   when 'Updated'
     <do something>
 end

I'd like to switch the behavior based on what the role is. This didn't work:

case record_type && role_type == 'RoleA'
   when 'New'
     <do something>
   when 'Updated'
     <do something>
 end

case record_type && role_type == 'RoleB'
   when 'New'
     <do something>
   when 'Updated'
     <do something>
 end

This code is skipped over and I'm assuming that Ruby is confused about which statement to use.

Upvotes: 1

Views: 872

Answers (2)

steenuil
steenuil

Reputation: 384

You can't pass an "argument" to case. The first term after case is an expression that returns the object it will match upon, and the expression you put in returns either true or false. You can either put it all inside an if expression, or put the two objects in an array and match on the whole array:

case [record_type, role_type]
when ['New', 'RoleA']
  ...
when ['New', 'RoleB']
  ...
when ['Updated', 'RoleA']
  ...
when ['Updated', 'RoleB']
  ...
end

Upvotes: 2

engineersmnky
engineersmnky

Reputation: 29328

Ruby is not "confused" you just only have 2 cases:

case record_type && role_type == 'RoleA' # true or false 

because record_type && role_type == 'RoleA' will only evaluate to true or false I think more what you are looking for is:

case role_type
  when 'RoleA'
    case record_type
       when 'New'
         #do something
       when 'Updated'
         #do something
    end
 when 'RoleB'
    case record_type
       when 'New'
         #do something
       when 'Updated'
         #do something
   end
end

That being said I would recommend looking into whether refactoring this is possible into something simpler like

def new_record(role_type)
  if role_type == 'RoleA'
    #do something
  elsif role_type == 'RoleB'
    #do something
  end 
end

def updated_record(role_type)
  if role_type == 'RoleA'
    #do something
  elsif role_type == 'RoleB'
    #do something
  end
end 

acceptable_record_types = ['New','Updated']
public_send("#{record_type.downcase}_record",role_type) if acceptable_record_types.include?(record_type)

This could be refactored even more if I understood the similarities between #do something

Upvotes: 1

Related Questions