Mathieu
Mathieu

Reputation: 4787

Ruby - use a Constant for 'case" statements conditions

I have a Ruby case statement that looks like:

case ruby_variable
when "instagram"
  # do this
when "twitter"
  # do that
  # and so on...
else
  "theres an error"
end

I also have a constant with all the social network names (this list willl vary in time):

NETWORKS_LIST = 
[   "instagram",
        "twitter",
        "pinterest",
        .......
    ]

I would like to change this so that the conditon values, that is to say "pinterest", "twitter" and others, populate automatically into my case statement (but keep the last line else "error").

Something like a loop:

case ruby_variable
when NETWORKS_LIST[0]
  do this
when NETWORKS_LIST[1]
  do that
and so on...
else
  "theres an error"
end

I'm not sure how to manage this.

Upvotes: 0

Views: 1377

Answers (1)

tadman
tadman

Reputation: 211600

Normally you use a structure like an Array to look up things and test validity, a Hash to define mappings, or a case to branch execution. It's highly unusual when more than one of these is involved at the same level of your solution, that is they're used in a way that's tightly inter-linked.

I think there's a few things that are confused here. Constants of this sort are best used for look-ups, like testing if your parameters are valid:

NETWORKS_LIST.include?(params[:network])

If you want to re-use values in that list elsewhere the Ruby convention is to prefer Symbols over Strings:

NETWORKS_LIST = [
  :instagram,
  :pinterest,
  :weratedogs
]

Then in your case statement:

case params[:network]
when :instagram
  make_instagram_post!
when :pinterest
  make_pin!
when :weratedogs
  bark_incessantly!
else
  raise "Not a valid network."
end

You maintain these two structures independently because the case statement has additional code in it that's not encapsulated in the original structure. Now you can always merge the two:

NETWORKS = Hash.new(-> {
  raise "Not a valid network."
}).merge(
  instagram: -> {
    make_instagram_post!
  },
  pinterest: -> {
    make_pin!
  },
  weratedogs: -> {
    bark_incessantly!
  }
)

This has a default value that's a Proc which raises an error, so you can just call it like this:

NETWORKS[params[:network].to_sym].call

That will either do whatever's expected or error out provided params[:network] is populated.

You can evolve this further into a little Ruby DSL if you want.

Upvotes: 2

Related Questions