1
votes

I'm trying to prevent the page from showing unless a params[:userid] is an integer.

I know the code is being called, because its not throwing errors, its not rendering, and I manually told it to render, then not render to check.

Here is what I'm using to try and do it:

render nothing: true unless params[:userid].is_a? Integer

And from reading up quickly on Rails, this should work, at least in theory I suppose. The route is setup properly because I checked it and had the page read back the :userid. There are no errors being thrown from the console, but here is the read out when using /account/jonathan/settings as the route:

Started GET "/" for 127.0.0.1 at 2015-09-28 23:04:24 -0400 ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations" Processing by PagesController#home as HTML Rendered pages/home.html.erb within layouts/application (1.1ms) Completed 200 OK in 124ms (Views: 117.6ms | ActiveRecord: 0.0ms)

Started GET "/" for 127.0.0.1 at 2015-09-28 23:04:31 -0400 Processing by PagesController#home as HTML Rendered pages/home.html.erb within layouts/application (0.0ms) Completed 200 OK in 15ms (Views: 14.9ms | ActiveRecord: 0.0ms)

Started GET "/account/jonathan/settings" for 127.0.0.1 at 2015-09-28 23:04:32 -0400 Processing by AccountController#settings as HTML Parameters: {"userid"=>"jonathan"} Rendered text template (0.0ms) Completed 200 OK in 1ms (Views: 0.8ms | ActiveRecord: 0.0ms)

Started GET "/account/jonathan/settings" for 127.0.0.1 at 2015-09-28 23:04:38 -0400 Processing by AccountController#settings as HTML Parameters: {"userid"=>"jonathan"} Rendered text template (0.0ms) Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms)

And when using /account/1/settings as the route:

Started GET "/account/1/settings" for 127.0.0.1 at 2015-09-28 23:27:00 -0400 Processing by AccountController#settings as HTML Parameters: {"userid"=>"1"} Rendered text template (0.0ms) Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms)

Started GET "/account/1/settings" for 127.0.0.1 at 2015-09-28 23:27:00 -0400 Processing by AccountController#settings as HTML Parameters: {"userid"=>"1"} Rendered text template (0.0ms) Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms)

I have tried using a route such as /account/1/settings and /account/jon/settings and neither show whats wrong.

3
In {"userid"=>"jonathan"} , the value is a String. So, what's the problem?Todd A. Jacobs
@CodeGnome Even when replacing Jonathan with 1 it still never rendershightekjonathan
Because "1" is a String, too. This whole question seems like an X/Y problem. What functional issue are you really trying to solve by having a condition render based on params[:userid]?Todd A. Jacobs
Im trying to use the param as a way to get a users access token for authentication before being able to access the page, other wise give them an error, or send them to a login page.hightekjonathan
1) That's insecure. Don't roll your own authentication; use devise or similar. 2) If you don't care about real security: redirect_to :login if params[:userid].blank? ensures that a userid is present.Todd A. Jacobs

3 Answers

2
votes

Problem

You are trying to redirect based on the presence of a value in the params hash. Per your comment above, the real underlying issue you're trying to resolve is:

Im trying to use the param as a way to get a users access token for authentication before being able to access the page, other wise give them an error, or send them to a login page.

Rendering nothing won't do that. Even if the logic succeeds the way you envision, that won't redirect them.

Furthermore, params hash values are always strings. As a result, branching based on an Integer as you currently do won't work.

Solution

Use a Well-Tested Authentication/Authorization Scheme

Authentication and authorization schemes are hard to get right. While you should feel free to apply them according to the needs of your application, rolling your own authentication mechanism is generally a really bad idea.

As a rule of thumb, you should use a security gem that is actively developed and is in widespread use, so that you can benefit from all the people who have vetted it for design effectiveness and bugs. Avoid security gems with low bus-factors unless you have a deeply compelling reason. Currently, devise is your best bet, but you can select from any widely-adopted authentication or authorization gem that suits your needs.

Fix Your Branching Bug

If you don't really care about security, and just want to fix your branching logic, you could call String#blank? to determine whether params[:userid] has a value. For example:

redirect_to :login if params[:userid].blank?

If you've implemented devise, there are a number of helpers to take care of these things for you, such as:

  • before_action :authenticate_user! to handle redirects for unauthenticated users.
  • user_signed_in? to return a Boolean based on the authentication status of the current user.

See Controller filters and helpers for more details.

0
votes

Next time paste your error message for easier help.

Now, what I would try is to add some parenthesis for human and machine clarity:

render(nothing: true) unless params[:userid].is_a?(Integer)

Try that and update your answer with the error message.

0
votes

I think params[:userid] is a String, like params = {userid: "1"}

You can write a method in controller or in Integer class and call it

render nothing: true unless is_integer?(params[:userid])

protected
def is_integer?(value)
  value.to_s.to_i == value
end