how to pass '?' character in url (rails) - ruby-on-rails

i want to pass a query to url like
http:/localhost:3000/saldo/;1010917745800000015?1
in my routes i have:
get 'saldo/:nomor' => 'kartus#show_saldo' , as: :show_saldo
and controller:
def show_saldo
#kartu = Kartu.find_by_nomor(params[:nomor])
end
but instead i get this params
Parameters {"1"=> nil,"nomor"=>";1010917745800000015"}
how can i get my param as {"nomor"=>";1010917745800000015?1"}

<%= link_to 'xyz' show_saldo_path(:nomor => 'nomor', :def => 'def'......) %>
In get everything you passed other than url parameter will become your query parameter. def will become your url parameter. More information here.

? is a special character in urls. If you want to include it in the value of a parameter then you should Uri Encode, eg with CGI.escape(), the parameter before submitting it: this will convert "?" to "%3F", and will similarly convert any other special characters (spaces, brackets etc). So, the parameter that is actually submitted will become "%3B1010917745800000015%3F1".
At the server side, rails will call CGI.unescape on the params, so it should show up in your controller as ";1010917745800000015?1" again.
This should happen automatically with form inputs - ie, if someone writes ;1010917745800000015?1 into a text field then it should actually be sent through as "%3B1010917745800000015%3F1"
If you want people to diagnose why this isn't happening then you should include the html (of the form or link which is submitting this value) to your question.

Related

Access old get parameters in URL after a post request

I have a form in RoR with a controller action that looks up a record via the get parameter.
def respond
if request.post?
# Submit logic here...
# cannot lookup this way to fill the form out again
# #current_message = Saved_message.find_by_id(params[:msg_id])
elsif request.get?
#current_message = Saved_message.find_by_id(params[:msg_id])
end
end
I can't use the params[:msg_id] to lookup the message again because it's a post request and I don't resend the get parameters. However, the get parameters remain in the url such as .../messages/respond?msg_id=2. I can get around this by passing in a hidden field with a different parameter name like <%= form.hidden_field :msg_id_2, value: params[:msg_id] %>. Then I can lookup the #current_message via the params[:msg_id_2]. However, I don't like this solution. Any advice to access the now inaccessible get parameter?
you should use RESTful routes so that you do not have to care about such issues.
since you are not posting much about the actual code or problem you are trying to solve, i can just assume what might be the issue here and how to solve it.

How does the params method work?

I have been trying to figure out how the params method works and I'm a bit stuck on the process.
For example, if a user clicks on a certain blog post in the index page, I guess that the link_to method calls the Post controller and the show action along with its block #post = Post.find(params[:id]) and then goes to the database to find the post and the view displays it.
So my missing link seems to be when is the post id passed into the params method?
Because the others already explained about params, I'm just going to answer directly a question of yours:
when is the post id passed into the params method
I think it's best explained with an example; see below:
say that you clicked a link:
/posts/1/?param1=somevalue1&param2=somevalue2
The Rails server receives this request that a client wants to view this GET /posts/1/?param1=somevalue1&param2=somevalue2 address.
To determine how the Rails server will respond, the server will first go to your routes.rb and find the matching controller-action that will handle this request:
# let's say your routes.rb contain this line
# resources :posts
# resources :posts above actually contains MANY routes. One of them is below
# For sake of example, I commented above code, and I only want you to focus on this route:
get '/posts/:id', to: 'posts#show'
From above notice that there is this :id, Rails will automatically set params[:id] to the value of this :id. This is the answer to your question where params[:id] comes from.
It doesn't have to be :id; you can name it whatever you want. You can even have multiple URL params like so (just an example):
get /users/:user_id/posts/:id which will automatically set the value on params[:user_id] and params[:id] respectively.
In addition to this URL params like :id, Rails also injects values to params[:controller] and params[:action] automatically from the routes. Say from the example above, get '/posts/:id', to: 'posts#show', this will set params[:controller] to 'posts', and params[:action] to 'show'.
params values also comes from other sources like the "Query string" as described by Mayur, and also comes from the body of the request, like when you submit a form (the form values are set within the body part of the request) and like when you have JSON requests, which all of these are automatically parsed by Rails for your convenience, so you could just simply access params and get the values as you need them.
Params are hashes in ruby with Indifferent access which means,
hsh = {"a" => 1, "b" => 2}
Consider this hsh as params returned from a POST request from browser, it's a key value pair with keys as string. Since it's a params so the values can be accessed as
hsh["a"]
=> 1
hsh [:a]
=> 1
params are formed on the client where the interface load, consider a form which has a submit button. When you press submit, the data filled in form or any hidden textboxes are formed into a hash and passed across the request. This when received on server end will be called as params or request params.
For Get requests: data send across the url will be read as params on backend.
GET: http://www.abx.com?user=admin
params on backend: {"user" => "admin"}
This will be displayed in rails server logs
For Put request: data send across the body will be called params.
PUT: http://www.abx.com
data: {"user" => "admin"} Client side
params on backend: {"user" => "admin"}
This will be displayed in rails server logs
How does the params method work?
The params come from the user's browser when they request the page. For an HTTP GET request, which is the most common, the params are encoded in the URL. For example, if a user's browser requested
http://www.example.com/?post=1&comment=demo
then params[:post] would be "1" and params[:comment] would be "demo".
In HTTP/HTML, the params are really just a series of key-value pairs where the key and the value are strings, but Ruby on Rails has a special syntax for making the params be a hash with hashes or array or strings inside.
It might look like this:
{"post"=>"1", "comment"=>"demo"}
Link to Rails Guides on params: guides

Is it safe to populate forms with params values?

I am using a form to filter records with fields not linked to an AR object. When form is submitted, I want to show records and populate the form with previously entered values so the user can see filtering parameters.
Form example:
= form_tag businesses_path, method: 'get' do
.field
= label_tag :title, 'Title'
= text_field_tag :title, params[:title]
= button_tag do
'Submit'
I'm thinking of using params to populate form inputs but not sure if it's safe? Or maybe there is a better solution?
Since we're dealing with RESTful interfaces with Rails the params hash is in essence the data in the message between the front end (browser) and the back end. It is there to be used to relay data between the user front end and your controller at the back-end. The params hash is one of the most important and versatile tools in RoR.
From the Rails guide: http://guides.rubyonrails.org/action_controller_overview.html#hash-and-array-parameters
You will probably want to access data sent in by the user or other parameters in your controller actions. There are two kinds of parameters possible in a web application. The first are parameters that are sent as part of the URL, called query string parameters. The query string is everything after "?" in the URL. The second type of parameter is usually referred to as POST data. This information usually comes from an HTML form which has been filled in by the user. It's called POST data because it can only be sent as part of an HTTP POST request. Rails does not make any distinction between query string parameters and POST parameters, and both are available in the params hash in your controller:
So use the params hash; it is a sound method for caching user input and re-displaying it, as was your question.
Caveat
Of course, if you're displaying from the hash and not the database store itself, you may encounter data synchronization problems. But as far as your specific question, I'd say use the params hash without a second thought.
It's absolutely fine. Rails will sanitise anything on it's own. Just don't call params[:title].html_safe when you printing "raw" user input.
You can store that params in a instance variable in respective controller action like flowing in controller.
def test_action
#title = params[:title]
end
And then set #title as field value as flowing
= text_field_tag :title, #title

URL helper method uses what default :id?

I'm new to Rails and had a doubt regarding the link_to method. The second argument should be the url of the link, which one can generate using the url helper methods. However, one may need to pass :id as an argument of the helper method, which can be done by passing an object (which has :id as one of its attributes).
Well, in one case I did not pass the object to the method (in one of the views). However, the url was still able to obtain the correct :id (presumably using an instance variable defined earlier).
How did Rails choose a value for :id when I didn't even pass in any object?
Thanks a lot!
Edit
Here's the relevant code:
link_to 'Find Movies With Same Director', same_dir_path
Here, I am on a "show" page with url /movies/1. The same_dir_path is the helper method for the URL /movies/same_dir/:id where :id would be that of the passed object and movie#same_dir is the controller#action. Note I did not pass any object to the helper method link_to and yet, it takes the :id from the previous url ('1' in this case). The URL isn't even relative to the previous one (the path is different).
This is the controller method (same_dir):
def same_dir
#movies = Movie.find(params[:id])
if (#movies.director.nil? || #movies.director == '')
flash.keep
redirect_to movies_path
flash[:warning]="'#{#movies.title}' has no director info"
return
end
#otherMovies = Movie.find_all_by_director(#movies.director)
end
This is the routes.rb code:
match 'movies/same_dir/:id'=> 'movies#same_dir', :as => :same_dir
resources :movies
After reading your updated question I can provide you with a better answer:
Rails controllers can have default url options via the url_options method. (Doesn't seem to be a very documented feature. (here and here))
By default this method returns the parameters from the current request and that is where the id is coming from.
You can override it, too:
def url_options
{ my_parameter: my_value }.merge(super)
end
Original answer (might still be useful):
What you are witnessing is most likely a browser feature. For example this code:
link_to "Show", ""
generates this HTML code:
Show
If you click that link in a browser it navigates to the empty url relative to the current url, which is in fact equal to the current url.
Another example:
link_to "Publish", :publish
generates:
Publish
Now if your current url is http://localhost/articles/1/edit that link will take you to http://localhost/articles/1/publish. (Notice that the final url contains the model ID even though you are not having it in the HTML source)
In both cases your current model ID is preserved by the browser because you are using relative urls.
This behaviour might give you the illusion of some magical model ID detection, especially because browsers preview the final (=absolute) url when hovering over the link.
Have a look at the source, I'll bet your generated links do not contain any model IDs.

Use a string with forward slashes as a single parameter in routes.rb

Sorry about that confusing title :) I have a resource, ComatosePage (used in the comatose cms plugin), which has a table called comatose_pages which has a field 'full_path' which has values like this: "en/home/logged-in/subscriber/school-top" to set up a route so that i can use this full_path field to load a ComatosePage from the db, instead of the standard id field, so that this url:
/comatose_admin/en/home/logged-in/subscriber/school-top
loads the comatose_admin controller's edit action, passing everything after comatose_admin/ through as a parameter, ie generates this for rails:
Parameters: {:controller => "comatose_admin", :action => "edit", :full_path => "en/home/logged-in/subscriber/school-top"}
The complication lies in the fact that the string is broken up with forward slashes, which is going to confuse routes, i think. Can i set up routes to take everything after "comatose_admin/" and put it into a single parameter?
You can use wildcards in your routes that will match forward slashes. Try something like this:
"/comatose_admin/*full_path"
Then params[:full_path] should contain the rest of the request path.
See Route Globbing

Resources