0

I am trying to set up a super simple RESTful endpoint (as an ApplicationController) that does simple path param validation and that returns a hardcoded JSON response:

{
  "foo" : "123",
  "bar" : {
    "whistle" : "feather",
    "ping" : "pong"
  }
}

The URL being hit is GET http://localhost/widgets/${widgetId}/${fizzbuzzId} where both ${widgetId} and ${fizzbuzz} are expected to be positive integers.

I'm trying to figure out how to check the value of ${widgetId} and ${fizzbuzzId} and throw a 400 if they aren't positive integers. I'm also trying to figure out how to return the hardcoded response string as the HTTP response entity with status code 200 if the two path params survive validation:

In the routes.rb:

resource :widgets

And then the controller:

class WidgetsController < ApplicationController
  def show
    if(params[:widgetId].to_i <= 0 || params[:fizzbuzzId] <= 0) {
      render json: { "error" : "bad path params" }, status: :not_found
      return
    }

    response = %(
      {
        "foo" : "123",
        "bar" : {
          "whistle" : "feather",
          "ping" : "pong"
        }
      }
    )

    render json: response, status: :ok 
  end
end

When I run this I get:

myuser:myapp myuser$ curl -k http://localhost:3000/widgets

SyntaxError at /widgets
==============================

> syntax error, unexpected '{', expecting keyword_then or ';' or '\n'
/Users/myuser/myapp/app/controllers/widgets_controller.rb:4: syntax error, unexpected ':', expecting =>
      render json: { "error" : "bad path params ...
                              ^
/Users/myuser/myapp/app/controllers/widgets_controller.rb:4: syntax error, unexpected '}', expecting keyword_end
...ad path params" }, status: :not_found
...                               ^
/Users/myuser/myapp/app/controllers/widgets_controller.rb:6: syntax error, unexpected '}', expecting keyword_end

app/controllers/widgets_controller.rb, line 3
----------------------------------------------------

``` ruby
    1   class WidgetsController < ApplicationController
    2     def show
>   3       if(params[:widgetId].to_i <= 0 || params[:fizzbuzzId] <= 0) {
    4         render json: { "error" : "bad path params ID" }, status: :not_found
    5         return
    6       }
    7   
    8       response = %(
```

App backtrace
-------------

 - app/controllers/widgets_controller.rb:3:in `'
 - app/middleware/catch_json_parse_errors.rb:8:in `call'

Full backtrace

Any ideas where I'm going awry?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
smeeb
  • 27,777
  • 57
  • 250
  • 447
  • 1
    To return repose: `render json: respose, status: :ok` For the params, rails has the `params` keyword. You can try to print it with `puts params` and see what it contains. – linnal Mar 27 '17 at 14:39
  • Thanks @linnal (+1) - please see my updated code that incorporates you're feedback. Is there a cleaner way to verify that the params are integers **and** positive? Also can you confirm that my 400 error response is correct? Thanks again enormously! – smeeb Mar 27 '17 at 14:49
  • @smeeb on a side-note, instead of writing your response as a JSON string directly, you can use a Hash, which will make interacting with your response object a lot easier, and use Rails's `Hash#to_json` method to generate a JSON string version of it. In fact if `response` is a Hash object this will be called automatically when you do `render json: response`. – omnikron Mar 27 '17 at 15:01
  • Welcome to Stack Overflow. It's not necessary, or particularly desirable to tell us whether you are new at using Ruby or Rails; We don't really care. We do care whether you asked a good question, showing research and effort. "[ask]" and the linked pages along with "[How much research effort is expected of Stack Overflow users?](http://meta.stackoverflow.com/questions/261592)" go into this. – the Tin Man Mar 27 '17 at 17:40

1 Answers1

1

You can check whether your params are positive integers by using this:

>> "23".to_i > 0
=> true
>> "foo".to_i > 0
=> false

So you could adept this for your params via params[:widgetId].to_i > 0 Does that make sense to you?

Also if you want to return your error response, you need to return "early" otherwise the controller will complain about a double render:

render json: { "error" : "bad input" }, status: :400 and return

Holger Frohloff
  • 1,695
  • 18
  • 29
  • Thanks @Holger Forhloff (+1) - I updated my question to contain your suggestion! Regarding `params[:widgetId].to_i <= 0`, will this be false even if `params[:widgetId].to_i` returns `false`? Or would `false <= 0` be a double-negative, resolving to `true`?! – smeeb Mar 27 '17 at 16:21
  • Also now that I'm able to start running the code I'm seeing errors in your suggestion. Any ideas as to what the fix is? Thanks again so much! – smeeb Mar 27 '17 at 16:55
  • 1
    @smeeb `params[:widgetId].to_i` returns 0 if `:widgetId="string"` What errors are you seeing? BTW: you can run `rails c` and try little commands from terminal :) – linnal Mar 27 '17 at 16:59
  • 1
    Thanks @linnal (+1) please see my updated question with the exact error...doesn't seem to like my error response json...any ideas? – smeeb Mar 27 '17 at 17:02
  • 1
    @smeeb updated your code. There should not be `and`, you need return so that you do not render twice, otherwise rails complains. – linnal Mar 27 '17 at 17:07
  • Thanks again so much @linnal (+1) - please see my updated error message, Rails is still not liking the syntax for some reason! – smeeb Mar 27 '17 at 17:16
  • @smeeb I think the problem is this `json: { "error" : "bad path params" }`, something that happens (If I find out why, I'll write you here, probably something with how rails parses params) , just assign the json to a variable: `response = { "error" : "bad path params" } ` and than `render json: response, status: :not_found` – linnal Mar 27 '17 at 17:21