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
Related
I have a function which calls a _path helper function with several parameters:
v2_specific_path(user, filter_params)
This works great, and in the controller method that handles this path I see both user and filter_params and their values.
In fact if I try to print out params they don't show up, but if I print out either one of them then they print out fine. filter_params has a helper function which builds a hash from several params[:keys] so that might be the reason.
What I'm trying to do is add another set of parameters to the function call:
v2_specific_path(user, new_params, filter_params)
Since I'm trying to add some functionality which requires passing some information to the underlying controller that resolves this request.
The problem is that this doesn't work and seems to screw things over:
If I put them in the middle: v2_specific_path(user, new_params, filter_params), then all the other params work great, but new_params actually appear inside params[:format] as: params[:format]="param1=4¶m2=hi
If I put them at the end: v2_specific_path(user, filter_params, new_params) then filter_params doesn't get parsed at all and appears in params[:format] but new_format does appear to be parsed and appear in params correctly
I can't seem to figure out why this is happening. I've made sure I have correct params.require/params.permit values in the controller.
Any help is appreciated, if anyone has any other alternatives to passing values from application_helper to a controller (via _path, or some shared variable) that would also help immensely
Thank you!
For anyone seeking a solution to this:
I fixed this by doing two things:
1) created proper new routes which suited my implementation (I tried to do something a bit too clever and decided to just create new relevant routes instead of doing something too dynamic
2) I added the params I needed in to the routes: /something/:param1/whatever/:param2 etc.
This worked for me
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 :)
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.
So basically I was creating some client methods that would create a path to hit an external service.
Also, I am using addressable gem.
Here is an example:
def get_member(ord_id, member_id)
path = '/organizations/{ord_id}/people/{member_id}'
hash = get(path, member_id: member_id, org_id: ord_id)
{ Member.custom_deserialize_method(hash) }
end
This works if the path is simple as above.
Now I want to write a method for a different path which does a bulk look up like this:
organizations/ab9176be/members/bulk?memberId=8e936891&memberId=b71c4f1e (This is not a web url. Its a service end point)
The above method can have multiple memberId params.
I know addressable has an expand method and ruby has a to_param method.
But I do not not know if that would help in my situation. I would appreciate some help here.
Route Globbing
I'm sure if this will help, but considering you've had no responses, I felt I'd be best posting
I learnt about route globbing a few weeks back. Bascially this allows you to define routes like this:
get 'books/*section/:title', to: 'books#show'
Would match books/some/section/last-words-a-memoir with
params[:section] equals 'some/section', and params[:title] equals
'last-words-a-memoir'.
Although not directly related to the solution for your question, it may help you appreciate how Rails processes some of the routes in the app. Essentially, it means you can add as many "wildcard" routes as you need, with the various elements of the route being compiled in the params hash
So, I'm implementing a pretty/SEO-friendly URL scheme for my rails app. I have a model called Artist, and I would like the Rails artist_path helper to always generate the friendly version of the path.
In my routes.rb file, I have the following line:
get 'artists/:id(/:slug)', :to => 'artists#show', :as => 'artist'
If the slug is left out, or is incorrect (it's calculated by the artist name), the controller 301 redirects to the correct URL. However, for SEO reasons, I want to ensure that all links internal to my site have the correct URL to start with.
The Artist model has the two following (very simple) functions to allow this to work:
def slug
name.parameterize
end
def to_param
"#{id}/#{slug}"
end
If I call artist_path with an artist object, this works as intended:
> app.artist_path(Artist.find 1234)
=> "/artists/1234/artist-name"
However, when I use call it with just the ID, it does not seem to use to_param at all:
> app.artist_path(id: 1234)
=> "/artists/1234"
tl;dr: How can I force Rails to always instantiate the object and call to_param on it when artist_path is called, even when only the ID is specified?
As far as I'm aware, the reason why what you're asking won't work is because when you pass in values to the built-in/automatic URL helpers (like an ID, per your example), those values just get used to "fill in the blanks" in the route URL.
If you pass an array, the values from the array will get used in order until the URL is filled in. If you pass a hash, those properties will get replaced into the URL. An object, like your model, will use it's to_param method to fill in the values... etc.
I understand your concern regarding "having knowledge of the limitations of that model," however, this behavior is standard in Rails and I don't believe it would really throw anyone. When you pass in an ID, as you do in your example, you're not telling the URL helper to "lookup a record via the model using this ID," you're simply telling it to "replace ':id' in the URL string with the ID you're providing." I'm fairly certain the built-in URL helpers wouldn't even know how to lookup the record - what model to use, etc. - other than maybe inferring from the route/controller name.
My best suggestion is to always use the instantiated model/record. If you were hoping the URL Helper would look that up for you, then there's no extra overhead as far as querying the database goes. If there's some additional reason you want to avoid instantiating the record yourself, I'd be glad to hear it and possibly provide other suggestions.