ahnbizcad
ahnbizcad

Reputation: 10797

How to create case(switch) statement with a hash of constants using ruby on rails?

I want to create the equivalent of this code, except using a hash and some meta programming.

def current_verb
  case params[:controller]
  when "apps"
    @current_verb = "MADE "
  when "articles"
    @current_verb = "LEARNED "
  when "articles"
    @current_verb = "WONDERED " # Change later to specify articles with a certain tag.
  else
    @current_verb = "IS "
  end
end

Intuitively, I tried something like this, but it seems to be invalid. So far I have this in the application_controller.rb

class ApplicationController < ActionController::Base

  before_action :current_verb

  private
    verbs = { pages: "IS",
              apps: "MADE",
              articles: "TAUGHT", 
              articles: "WONDERED"
            }

    def current_verb
      case params[:controller]

      verbs.each |key, value| do
        # need this to spit out literal code, not evaluate code
        when key
          @current_verb = value
      end

      else
        @current_verb = verbs[:pages]
      end
    end

The tricky part about this is that I don't think I can use define_method or send because the looped portion isn't the entirety of the method. Thanks for the help.

Upvotes: 0

Views: 1397

Answers (1)

pdobb
pdobb

Reputation: 18037

It looks like you're just looking up a key in a hash and returning its value. The only caveat appears to be that if the ke isn't found then you want to return a default value of "IS". I would suggest using Hash#fetch for this.

class ApplicationController < ActionController::Base
  VERBS = { pages: "IS",
            apps: "MADE",
            articles: "TAUGHT", 
            articles: "WONDERED"
          }.stringify_keys.freeze

  before_action :set_current_verb

  private

  def set_current_verb
    @current_verb = VERBS.fetch(controller_name) { "IS" }
  end
end

Note that I made VERBS a constant so that it would be visible to the set_current_verb method. And I included it above the private designation because constants can't be private anyway. Using the VERBS hash inside of the set_current_verb method would cause it to be evaluated every single time, so the constant is a better solution still. Also, controller_name is preferred over params[:controller] for its expressiveness and because it will avoid returning namespaces should any exist in the future.

Also, the VERBS hash seems to have two identical keys. I assume that's just a typo and can be corrected by you.

Upvotes: 2

Related Questions