Validating API input - ruby-on-rails

Various parameters are appended to the API URL.
There is data that needs to be validated by ruby (as rails does not process validations before creating/modifying data) before processing.
The following returns true with a given string, but the parametrized version always returns true
!1e48.is_a? Integer
(!params[:id].is_a? Integer)
I realise rails considers all paramters as strings, but converting the params to_i or some other type leads onto a garden path. What would be appropriate syntax?

Use more restrictive Kernel#Integer function:
!(Integer(params[:id]) rescue nil)

Related

Saving Mutiple arrays with strong parameters Ruby on Rails 4

I have an ajax response like this ,
google_searched_locations [{"geometry":{"location":{"J":31.482273,"M":74.33069999999998}},"icon":"https://maps.gstatic.com/mapfiles
/place_api/icons/restaurant-71.png","id":"b93a99a46343de01d0d928f99470f9b0f5f6f11d","name":"Dunkin' Donuts"
,"place_id":"ChIJSeoh6hkEGTkRsd0e1crAbHU","rating":4.3,"reference":"CnRhAAAAewgE30hrAcax1xdGPIf7M863
bOtNhRgfnncMx17uWMgtdTyGHGbTO76LX6yXsPyB4PcvfVzIeeIR1bxG0oSambqMYxFWwqHY3Cyfs6uWFp2QbVkGObvQ1LlTrdqLh1eZVgX8aL0iRFFhAnHEM8u1RxIQACDCn2BMD3IiG7tKri31BRoULMSagTU-EmxswgLxzCOWPVVnlpI"
,"scope":"GOOGLE","types":["restaurant","food","point_of_interest","establishment"],"vicinity":"Lahore"
,"html_attributions":[]}]
After JSON.parse(thisString) , I get the required result by using params["places"][0]["geometry"] and then looping over it , but I know that it's not a better way when Rails have strong parameter there , so I tried some solutions after searching , below is my strong parameters function
def google_places
json_params = ActionController::Parameters.new(JSON.parse(request.body.read) )
json_params.require(:google_searched_locations).permit(:icon)
end
but it gives the following error ,
JSON::ParserError in SearchesController#searchResults
757: unexpected token at 'places=%5B%7B%22geometry
Can anyone make us out of this mess , and tell us what's happening here and where is the right way to go .
Thanks in advance :)
You do not need to manually parse JSON parameters. Rails will automatically parse the parameters provided the request has the correct format (more specifically the correct mime type headers). In fact doing so will be slower and use more memory since you are doing the same parsing work twice.
To allow an array of parameters you simply use the hash key and an array of the permitted attributes for the nested params.
def google_places
params.permit(places: [:icon, { location: [:H, :L] }])
end
If possible you should change the H and L parameters to lowercase so that you can map them directly to attributes without violating the ruby conventions of lowercase attributes.

rspec, validate the actual Expectation parameter

Is it possible to validate the actual parameter received by a mock objects method parameter? I cannot do a direct comparison because i'm using Fabricate and converting the object into a serialised format.
for example:
expect(user).to have_received(:add).with(valid_user())
so in that case valid_user() would accept the parameter, validate and return a boolean, to verify a valid value was passed into user.add()
can something like that be done?
So far I've been reading the documentation in https://github.com/rspec/rspec-mocks regarding Argument Matchers
Edit: in my specific case, the argument is a quite large string. I would like to validate that the string is valid by potentially running a regex against the string. So i would like to run the argument through a validation method which simply returns true/false.
You can use a custom matches in with() as shown in the spec docs https://relishapp.com/rspec/rspec-mocks/docs/setting-constraints/matching-arguments#using-a-custom-matcher

ruby on rails session data returns false even when data exists

I have a code like,
session[:my_data] = 'abcd'
and when i try to get,
puts session.has_key?("my_data") then it returns false always.
Ruby allows any object to be a hash key. If the hash key is a symbol, you will not be able to access it using a string.
In this case, you have various options:
convert the string to a symbol
session.has_key?("my_data".to_sym)
use Rails' with_indifferent_access method to allow both symbol and string queries on the hash
s = session.with_indifferent_access
puts s.has_key?("my_data")

rails params validation in controller

Is there a best practice to validate params in a controller?
#user = User.find_by_id(params[:id])
If I tamper with the param to give it an invalid :id param, say by visiting "/users/test", I can generate the following error:
Conversion failed when converting the nvarchar value 'test' to data type int.
I am thinking right now of params that won't go straight to a model and can be validated by model validations.
Yes you should always validate your parameters. People can always mess around with the parameters in their web browser's address bar, or modify parameters stored in the DOM. Another example where parameters can be screwed up is if the webpage is left open a long time. Imagine someone is viewing the page "/users/3/edit" and leaves it open for an hour, then hits refresh. In the mean time that user may have been deleted. You don't want your website to crash - it should handle that gracefully.
Depending on your database and adapter, doing User.find_by_id("test") will not crash. But your database/adapter was not able to convert the string in to an integer. One thing you can do in this particular case is use Ruby's .to_i method.
User.find_by_id(params[:id].to_i)
If params[:id] = "12", Ruby will convert that to the integer 12 and the code will run fine. If params[:id] = "test", Ruby will convert that to the integer 0, and you should never have a database record with an ID of 0.
You can also use regular expressions to test if a string is an integer.
But in general, yes, try to always validate your parameters so you can handle errors gracefully and control the data coming in.

how to parse multivalued field from URL query in Rails

I have a URL of form http://www.example.com?foo=one&foo=two
I want to get an array of values ['one', 'two'] for foo, but params[:foo] only returns the first value.
I know that if I used foo[] instead of foo in the URL, then params[:foo] would give me the desired array.
However, I want to avoid changing the structure of the URL if possible, since its form is provided as a spec to a client application. is there a good way to get all the values without changing the parameter name?
You can use the default Ruby CGI module to parse the query string in a Rails controller like so:
params = CGI.parse(request.query_string)
This will give you what you want, but note that you won't get any of Rails other extensions to query string parsing, such as using HashWithIndifferentAccess, so you will have to us String rather than Symbol keys.
Also, I don't believe you can set params like that with a single line and overwrite the default rails params contents. Depending on how widespread you want this change, you may need to monkey patch or hack the internals a little bit. However the expeditious thing if you wanted a global change would be to put this in a before filter in application.rb and use a new instance var like #raw_params
I like the CGI.parse(request.query_string) solution mentioned in another answer. You could do this to merge the custom parsed query string into params:
params.merge!(CGI.parse(request.query_string).symbolize_keys)

Resources