mr_muscle
mr_muscle

Reputation: 2900

Rails return json depends on webhook action to be in line with DRY

I've got a webhook receiver service where in a response I need to send specific json. I want to be in line with DRY policy so I don't want to repeat the same code in 22 places. Expected json should looks like:

  render json: {
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            "here is the text depends on action",
          ],
        },
      },
    ],
  }

sample 3 actions will be like:

  def create
    action_name = params[:webhook][:queryResult][:intent][:displayName]

    case action_name
    when 'get-calendar'
      render json: {
        "fulfillmentMessages": [
          {
            "text": {
              "text": [
                "show user's calendar",
              ],
            },
          },
        ],
      }
    when 'get-room'
      render json: {
        "fulfillmentMessages": [
          {
            "text": {
              "text": [
                'show available meeting rooms',
              ],
            },
          },
        ],
      }
    when 'login'
      render json: {
        "fulfillmentMessages": [
          {
            "text": {
              "text": [
                'login user',
              ],
            },
          },
        ],
      }
    end
  end

Like I wrote I've got like 21 actions here and the only thing that changes is: "text": [ 'text depends on action', ], Is it possible in the case of json not to repeat the same code?

Upvotes: 0

Views: 60

Answers (1)

Oleksandr Holubenko
Oleksandr Holubenko

Reputation: 4440

I think the best solution here is to move this case logic to hash:

ACTIONS = {
  "get-room" => "show available meeting rooms",
  "get-calendar" => "show user's calendar",
}

def create
  action_name = params.dig(:webhook, :queryResult, :intent, :displayName)

  render json: prepare_response(action_name)
end

def prepare_response(action_name)
  {
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            ACTIONS[action_name],
          ],
        },
      },
    ],
  }
end

For future it's also possible to add something like "validations" (guards)

def create
  action_name = params.dig(:webhook, :queryResult, :intent, :displayName)

  return 'what ever you want here' if action_name.blank?
  return 'here as well' if ACTIONS.keys.exclude?(action_name)

  ...
end

Upvotes: 3

Related Questions