Rails 5 Params / Strong Params issue - ruby-on-rails

I have a RESTful API (ActionController::API) service that accepts a list of params. The RESTful service takes a JSON body request (with Content-Type of application/json). When I debug the controller/action (right after the action def) and take a peak at the params list, it appears as follows:
<ActionController::Parameters {"given_name"=>"Mark", "subdomain"=>"development", "controller"=>"user", "action"=>"create", "user"=>{"given_name"=>"Mark"}} permitted: false>
EDIT
All the request has in it (when it is passed to the controller/action -- using POSTman):
{"given_name":"Mark"}
Notice that the object contains the given_name params twice. Is this normal behavior? I did not pass a "user" object (json object) to the controller/action? What is the permitted flag?
When I try to use (right now I'm just testing RESTful call and assigning any values that the user object will except... no validations have been programmed yet):
user = User.new(params)
I get the error:
#<ActiveModel::ForbiddenAttributesError: ActiveModel::ForbiddenAttributesError>
So, I've looked everywhere for the reasoning behind this (why is there a "user" key in the params list? What is the purpose of the permitted flag? Why am I getting an error when I try to assign params)?
EDIT
After doing some testing, I change the controller name from "user_controller" to "tester_controller" and setup the routes to point to the renamed controller.
It seems the "user" object in the params list above has changed to "tester". So why does the param list contain an "object" with all the passed params with the name of the controller? If that's the case, why is it needed?
Any help would be greatly appreciated.

By default Rails in API mode wraps JSON request parameters into a hash guessing its name from controller class. That's why changing the controller from User to Tester changes "object" name. You can read details here.
So if you don't need this "object" in your params just remove :json from :format array in config\initializers\wrap_parameters.rb. Or you can use fine-grained control at the controller level as described above.

You need to specify which attributes are acceptable for mass-assignment in your controller.
def create
#user = User.new(params.require(:user).permit(:given_name))
end
This prevents malicious users from making request posts that alter attributes internal to your application, like role in the case of a user object.
As mentioned above, a better explanation can be found in the guide referring to strong parameters.

You can't pass params to constructor, because params always contain :action and :controller keys. Attributes for new objects should be put in hash under key that identify model you want to create e.g. :user. I suggest you to consult rails guides, especially chapter 7 of "Form Helpers" guide.
If you want to learn more about strong parameters there is a chapter in rails guides for that too :)

Related

How param works in rails views

I have an old app running in rails 2.3.5
In customizing, I stuck when i find a param keyword being used in views
i.e in views I can see stuffs like
unless params[:fee_collection].nil?
can someone explain to me in what context is param keyword used in rail views rather than controllers
params is a hash that contains parameters sent with the HTTP request.
You can access to this object as well from your controller or from a view. Although, the convention is to access to an instance variable (defined in your controller, e.g : #fee_collection = params[:fee_collection]) from your view.
The params variable stores a hash which contains the http parameters received in the request to this route (controller#action)
If you have a UserController with the show method, you should receive the param[:id] to identify the resource you're looking for.
If you want to send parameters, it would be either via url in a GET or a data payload on a POST request, on the most common cases.

Rails 4 - controller strong params - generated with scaffold

I am trying to make an app in Rails 4.
I use scaffolding generators to make my resources starting points.
I'm noticing, when I ask questions on this board, that people comment on the form of my strong params definitions in the controllers.
The scaffold generator creates them this format:
def industry_params
params[:industry].permit(:sector, :icon)
end
Most resources that show how to whitelist strong params, show this format.
def industry_params
params.require(:industry).permit(:sector, :icon)
end
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
Is there anything wrong with the way the rails scaffold generator creates this method?
The require method ensures that a specific parameter is present, and if it's not provided, the require method throws an error. It returns an instance of ActionController::Parameters for the key passed into require.
The permit method returns a copy of the parameters object, returning only the permitted keys and values.
As you can see while using scafffold's default system we need to check for is there is any value in the params, whereas require throw an error if its missing.

Don't understand when a ROR View will/will not have a param for a model

I am having difficulty understanding how to cause a View in ROR4 to have a param for a model. It shows up when I try to use strong parameters in a controller, specifically:
def model1_params
params.require(:model1).permit(:attr1,attr2)
end
Sometimes it works. Sometimes I get "param not found: model1"
My understanding is that it fails (when it does) because the web page being submitted doesn't have any param called "model1" and that it works (when it does) because something I have done has caused the web page submission to have this param. In the latter case, the param is a hash representing the fields of the model, with members for attr1, attr2, etc.
Does it work when I use "form_for" (which specifies a model) but not the other kind of form call, which is not tied to a model?
Note: I am writing because I've had this problem for several weeks with no progress. I have searched the Rails doc and lots of instructional examples on the web but with no luck. I know I'm being dense, but so far I've not found a real API reference document, nor a real API programmer's guide that covers strong parameters.
I've found lots of examples on strong parameters but none of them clearly explain how it works, that would let me figure out on my own what I am doing wrong.
Say your controller's method is associated to a route model1_controller_method_path.
Your method can be called from a link in a view, and if the model1 parameter is not present, yes, you will get a 'param not found' error. To avoid this, make sure to have your parameter passed from your link_to as in:
link_to model1_controller_method_path(:model1 => the_value_you_want)

Using parameter[:user_id] ,params[:user_id], params["userid"] in Rails?

While studying a Rails application I saw statements like:
parameter[:user_id]
params[:user_id]
params["userid"]
Can anyone tell me if there any major difference between them? Or, are all
fetching parameters only and can I use them interchangeably?
parameter[:user_id]
I don't think this is something official. However there's a parameters method on the current request object. See request.parameters in a controller action.
params[:user_id]
Using the params[:user_id] is the same as calling request.parameters[:user_id]. Also params[:user_id] is the same as params["user_id"]. See HashWithIndifferentAccess.
I am not sure if that's just a typo on your part, but params[:user_id] and params["userid"] are not the same, even with HashWithIndifferentAccess. The _ won't just go away so they can hold different values.
No, you need to look at the context in which each one is used. params is the normal parameter hash made available to methods in your controllers. It contains the parameters passed in as part of the request as GET or POST params.
So, given the following URL:
http://www.testsite.org/some_resource?user_id=13
The params[:user_id] would contain the value 13.
If the URL instead was:
http://www.testsite.org/some_resource?userid=13
You would need to use params[:userid] to get the value. So it all comes down to the way the URLs are made for the different controllers.
There's a third way, where you can map parts of the URL itself to params in the routes into your application. See config/routes.rb in your application. For instance with the following route:
match '/user/:user_id' => 'users#show'
You could pass in an URL like this:
http://www.testsite.org/user/13
And in your UsersController.show method you could access the user id by using params[:user_id] like normal.
The parameter hash is most likely a local copy of or reference to the params hash in a helper method or something.
params and parameters are the same. They return both GET and POST parameters in a single hash.
There is no such a thing as parameter.
ref: rails api

Create a routes to a controller without model with a /id

I have product with a foreign collection_id key
I want to pass an id to a controller.
To do so i have the following routes for my controller :
controller :magasin do
get "magasin" => "magasin#index"
end
The only view in my controller is magasin/index.html.erb
The link to magasin is link_to collection.nom, magasin_path(collection)
This kind of syntax usually works in controllers with models. Here my link is : http://localhost:3000/magasin.2 instead of http://localhost:3000/magasin/2
Later on i will need to call the same view with product_kind_id instead of collection_id and i will add sort by name/price ....
How can i have the ID as a normal argument (/:id)instead of a type(.id)?
A popular URL schema to follow is RESTful routing. Rails has this built-in and will set it up for you if you initialize your resource via rails generate scaffold Magasin nom:string.
If you put resources :magasins in your routing file, it will route /magasins to MagasinsController#index and /magasins/1 to MagasinsController#show with params[:id] set to "1". It will also set up a few other routes that will be useful in the future but for now will just raise an action not found exception.
You don't want to use the dot as an argument delimiter, since Rails places what comes after the dot in the request.format method or just in params[:format] (ordinarily accessed through the respond_to method that comes with the generated scaffolds). Save that dot for later when you are working on delivering alternative display formats like XML and JSON.
I realize I've said a lot in a small space, so feel free to ask any follow up questions once you've consulted the Rails Guide on the issue, and I'll be very glad to help!

Resources