0

I have a method1 which calls other methods depending on params and then returns a json. One of these methods checks if a specific user exists. If the user doesn't exist the method should render a JavaScript alert. At first I got an error that render was called multiple times (which was correct). So I tried adding break but received an invalid break error. So I tried return but then I still get the Render and/or redirect were called multiple times in this action. How can I break out of method1 when I'm in method2, so that only the render in method2 gets called?

def method1
  data = case params["foobar"]
    when "case1"
      methodxy
    ...
    else 
      method2
    end
  render json: data
end

def method2
  if user.exists?
    return {...}
  else
    render(
      html: "<script>alert('Unknown user!')</script>".html_safe,
      layout: 'application'
    )
    return
  end
end
loelu
  • 85
  • 10
  • either way, there will be situation where you call render multiple times. So, you need to add your `render json: data` in a different condition where you don't want the json data to be rendered! – hiradyazdan Oct 06 '17 at 12:26
  • Possible duplicate of https://stackoverflow.com/questions/26446375/is-it-possible-in-rails-to-check-whether-a-redirect-or-render-had-already-been-i – spickermann Oct 06 '17 at 12:26
  • @hyphenbash so there's no way to break out of method1 without it rendering the json? – loelu Oct 06 '17 at 12:27

1 Answers1

2

Technically you could achieve this with a throw ... catch, which is essentially acting like a GOTO statement. But I would not advise this; the code is already too messy, and you'd be making the problem worse.

Instead, you should aim to clean up the flow in method1. Make the logical flow and responses clearer. For example, maybe something like:

def method1
  if !user.exists?
     render(
      html: "<script>alert('Unknown user!')</script>".html_safe,
      layout: 'application'
    )
  else
    data = case params["foobar"]
      when "case1"
        methodxy
      ...
      else 
        method2
      end
    render json: data
  end
end

def method2
  # ...
end

You could then refactor this further, e.g. by moving the user.exists? check into a before_filter and moving that case statement into its own method, to simplify things.

The end result could look something along the lines of:

before_filter :ensure_user_exists, only: :method1

def method1
  render json: foobar_data
end
Tom Lord
  • 27,404
  • 4
  • 50
  • 77
  • Thank you, I'm quite new to Rails and programming in general and I've never heard of `before_filter` – loelu Oct 06 '17 at 12:32