How to hidden query-string in Rails - ruby-on-rails

I wanna pass to a resource in a request for example
# Go to payment link
<%= link_to 'Payment', checkout_path(pricing: amount.id) %>
When I go to payment link the url path is the next:
http://localhost:3000/checkout?pricing=amount_2aHUHuhdn23jnSJd
I'd like to hidden the query-string "pricing=amount_2aHUHuhdn23jnSJd" without have to used any gem
UPDATE QUESTION 31/12
This request is of type Get since I need to show the different prices to the user, that's why the parameter pass (pricing: amount.id)
<%= link_to 'Payment', checkout_path(pricing: amount.id) %>
get 'checkout', to: 'subscriptions#checkout'
I'd appreciate your time and your grain of sand

You could store it in the Session.
Store it when the user enters the page, clear it when user clicks a link.
# SomeController#before_payment
session[:pricing] = amount.id
#then..
# CheckoutController#index
pricing = session[:pricing]
session[:pricing] = nil
Be careful because it will only live within the session. It will be stored as a cookie, and have a 4kb limit for data.

When the value is sensitive then hiding the value doesn't really fix the problem. Instead, I would suggest encrypting the value in the URL or to use another non-sensitive value instead.
Value encryption
You could use Rails MessageEncryptor to encrypt the value before passing it to the URL and decrypt it later in the controller again.
# in app/models/url_encrypter.rb
module URLEncrypter
ENCRYPTER = ActiveRecord::MessageEncryptor.new(
Rails.application.secrets.secret_key_base.first(32)
)
def encrypt(value)
ENCRYPTOR.encrypt_and_sign(value, purpose: :url)
end
def decrypt(value)
ENCRYPTOR.decrypt_and_verify(value, purpose: :url)
end
end
# when building the URL
<%= link_to 'Payment', checkout_path(pricing: URLEncrypter.encyrpt(amount.id)) %>
# when reading the param in the controller
pricing = URLEncrypter.decyrpt(params[:pricing])
amount = Amount.find(pricing)
Have a second non-sensitive, unique identifier
Here you add a second unique identifier to your database table, for example, a column named uuid which you could populate automatically in a before_save callback with self.uuid = SecureRandom.uuid
You can then use its value instead of the id like this:
# when building the URL
<%= link_to 'Payment', checkout_path(pricing: amount.uuid) %>
# when reading the param in the controller
amount = Amount.find_by(uuid: params[:pricing])

I'm not quite sure what you mean without seeing your routes.rb file. As mentioned by #Deepak Kumar to hide query from your url you should use POST request. Have a look at this guide. You can add below
post 'payment', to: 'checkout#payment'
In your routes.rb. This will call Payment action from your CheckoutsController

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.

Rails: Generating a link

I want to generate a hyperlink through combining records from my DB. Here is an example:
token_id value is 123456789
user_name value is Peter
brand_id value is 8
The token_id+brand_id+user_name should be combined to a new array like unique_id so you'll get this as a result:
Unique_id=123456789-8-peter
Then I want to put the result inside a clickable URL, like:
example.com/?campaign=XYZ?Unique_id=<%= unique_id %>
Do you have any ideas?
It's hard to know what you are actually trying to achieve here but i'll have a guess.
For a start, that's not a valid url: the url must have only one ? as this tells it when the path ends and the parameters start. (if you want ? in param values you'll need to url encode it but i don;t think that's what you had in mind). An example of a valid url would be
http://example.com?campaign=XYZ&unique_id=123456789-8-peter
which has "/" as the path and then two parameters (campaign and unique_id)
Note that i've used "unique_id" (downcased) as the second param name: by convention param names are all downcased.
To make the link:
<% unique_id = [token_id, user_name, brand_id].join("-") %>
<%= link_to home_path(:campaign => "XYZ", :unique_id => unique_id) %>
This assumes you've defined a route called "home" which points to "/". This will need to point to some controller and default action, eg your home controller and "index" action. It also assumes that the variables token_id, user_name and brand_id have been defined somewhere.
Alternately, you might want a url like this, which loads a campaign:
http://example.com/campaigns/XYZ?unique_id=123456789-8-peter
Note the path is now "/campaigns/XYZ" rather than just "/". By convention this would call your CampaignsController's "show" action, passing "XYZ" as params[:id]. you will also get 123456789-8-peter in params[:unique_id].
To generate this link in rails using the link_to helper it might be something like
<% unique_id = [token_id, user_name, brand_id].join("-") %>
<%= link_to campaign_path(#campaign, :unique_id => unique_id) %>
this expects #campaign to have been defined.
You can add to model:
def to_param
[token_id, brand_id, user_name.parameterize].join("-")
end
More information you can find here: Friendly URLs

rails: pass 2-d array to link_to

I have a controller querys with an action send_file.
querys_controller.rb
def send_file
send_data(params[data], :filename => "query.txt")
end
in html.erb I have:
<%=link_to "send data", :controller=>"querys", :action=>"send_file", :data=>#mat, method: :post%>
By clicking on"send data" rails shows me "Bad request" due to the fact that #mat is a 2-D array and it seems I link_to cannot send such structure. How can I send my matrix to my controller ?
#mat:
[["1681", "", "02.05.1955"], ["1680", "", "02.03.1936"], ["1679", "", "26.11.1938"], ["1692", "", "15.05.1958"]]
#Tonja, to me it seems to be very strange what you are doing. First you somewhere generate an array, then pass it over using the browser again back to your application. And then you send it back to the browser in a text format?
You should not pass this array to the user, but keep it on the server. Just store it in the database. Do not pass data to the user, only when absolutely neccesary. Your current implementation also forces you to do quite some checks on the data that is passed.
In the controller method that generates the html.erb, store the #mat instance somewhere, and get the ID of the record. Pass this ID to the link_to, and use this data from the DB as parameter for the send_data call.
(Small tip: do not actually use the ID, that is not secure, but use a random value. Or even better: do not pass anything at all if you can attach the value to the current_user).
You get the Bad Request because Rails does not understand the format you request. And that is because you assemble the url yourself. Use a call like
link_to "send file", send_file_querys_path(format: :txt)
or even a
button_to ....
if it is a POST operation.
You can get the valid routes with 'rake routes'. This makes your app better testable.
I hope my answers help you to rework your code. If what you are doing is the right way, then #m_x gave you the correct pointers.
Best regards,
Hugo
when passing url arguments in the form of a hash, you should separate them from the rest of the arguments for link_to:
<%
= link_to "send data",
{controller: "querys", action: "send_file", data: #mat},
method: :post
%>
However, this will pass the data as query parameters. If you really want to pass the data as POST parameters (for example, if #mat contains a lot of data), you will have to use a form tag with a hidden field and a submit button.
IMO a more efficient approach would be to pass the parameters that were required to populate #mat, repopulate the variable server-side and use it in send_file.
The best practice in this regard is to leverage rails' format capabilities, for example :
def some_action
#mat = populate_mat(params)
respond_to do |format|
format.html
format.txt do
send_data(#mat, :filename => "query.txt")
end
end
end
(note : for this to work, you will probably have to register the txt mime type in config/initializers/mime_types.rb)
then in some_action.html.erb:
<% = link_to "send data", {format: :txt}, class: 'whatever' %>
This will will just add a .txt extension at the end of the current url, which plays nicely with the REST paradigm (one endpoint per resource, with the extension indicating the desired representation).
You can also pass the format option to any url helper, for example :
<%= link_to "root", root_path(format: :txt), class: 'whatever' %>
Try this:
link_to("Send data", send_file_querys_path(data: #mat), method: :post)

Rails Forms for custom actions

I'm trying to link the input of a form to a specific action in my rails app.
Currently if I go to www.myapp.com/check/:idNumber, I'll be able to trigger the action just fine (which means routes is setup properly?). This action is basically a function call to a ruby/rails script with the parameter "idNumber" being passed to it. If the function is successful, it would return a newly created "Person" object and nil otherwise. This is different than the standard new operation as it determines the the attributes based on some information that it obtained from a database somewhere else.
Rake routes does give me the following:
check /check/:idNumber(.:format) person#check {:id=>/\d+/}
What I'm having trouble implementing is the form itself.
<%= form_tag("/check", :method => "get") do %>
<%= text_field_tag(:idNumber) %>
<% end %>
Controller action:
def check
regCheck = RegCheck.new
#person = regCheck.check_id(params[:idNumber])
if #person.name == nil
redirect_to root_path
end
end
submitting the form above would bring me to myapp.com/check?utf8=✓&idNumber=1234 instead. Can someone tell me what am I doing wrong?
I believe that using the check_path helper that is generated from the routes file is your best bet.
The form should look like this then.
<%= form_tag(check_path) do %>
<%= text_field_tag(:idNumber) %>
<% end %>
Rails forms can be finicky, especially when trying to build really customized forms.
This line
= form_for [#object]
Determines where the form goes, as well as the object that is being implemented. If you want to route the form to a different place, you can user the :url option. This options determines the path of the form, however you must keep in mind that the method is determined by the #object. If it is a new object, the method will be POST, an existing object will use a PUT method.
Let's suppose you want to update an existing object, but you want to send in data for a new object belonging to the existing object. That would look like
= form_for [#object], :as => #child_object, :url => my_optional_custom_path do |f|
# etc...
This generates a form sending a PUT request to the custom url (or the update path for #object if no custom url is supplied. The PUT request is sent with the parameter params[:child_object].
Hopefully this helps!
Best,
-Brian
I don't think it's possible the way you're trying.. The URL for the form is created before the user inputs any data.. So you need to remove the :idNumber from your routing..
If you do you get the following route:
check /check(.:format) person#check
Because the regex is removed now, you need to do this in you're controller:
def check
# Make sure ID is digits only
idNumber = params[:idNumber].gsub(/[^\d]/, '')
regCheck = RegCheck.new
#person = regCheck.check_id(idNumber)
if #person.name == nil
redirect_to root_path
end
end
You're form is allright, but you may want to use check_path like TheBinaryhood suggests..
If you really want it to be check/:idNumber you may also be able to submit the form to another action and redirect it to the right path from there..

Ruby On Rails: using arrays with link_to

I was curious on how to use arrays in the link_to method in ruby on rails for example:
Controller:
def index
#test = [1,2,3]
end
View:
<%= link_to "test", {:action => 'index'}, :test => #test %>
When looking at the source then, I end up with something to the effect of:
test
My guess is that the array's to_string or something similar is getting called to set the value of test in the html.
My goal is to be able to have a form in which people can submit data on the page, and then once they've submitted the data and return to the page, if they click on the link the data will persist through clicking on the link.
*Ideally I would like to do this without having to pass the parameters in the url.
Thank you.
If you want to keep data you should probably use cookies. They are very easy to use, just assign a value with the following in the action:
cookies[:some_key] = "some value"
and retrieve it with this:
cookies[:some_key] # returns "some value"
However, just to clarify what link_to is doing in your example:
<%= link_to "test", {:action => 'index'}, :test => #test %>
When looking at the source then, I end up with something to the effect of:
test
The reason is that you are passing #test to the third argument in link_to, which is a hash of html attributes, hence why it's turned into one. To have it become an parameter on the link, you need to pass it with the second, eg, {:action => 'index', :text => #test}. As noted above, however, this is not necessarily the best way to tackle this and, in addition, it's usually best to also pass the controller name to link_to or, better yet, use a named route.
If I understand well, you want to keep the datas submitted by the user after they validate the form ?
Well Rails is able to do that without any of your code line needed.
Based on the supposition that you have a route resource "objects"
In your controller :
def edit
#object = Object.find_by_id params[:id]
end
def update
#object = Object.find_by_id params[:id]
if #object.update_attributes params[:object]
# The datas have been successfully saved. You redirect wherever you want to.
else
render :action => 'edit'
end
end
and in your view :
<% form_for #object do |f| %>
<%= text_field :name %>
<% end %>
When the form fails to validate, the "name" text field automatically gets the previous entered data.
If after that you still need to reload your datas, you don't need to add them as a parameter in a link tag.
You get the object in your controller and passes it's datas to the view where you display it.
I would just write a view helper that formats it into a string with good separators, like commas.
That isn't a good way to be passing along information though. Try session variables, cookies, or url-encoded variables instead.
The best match to what you are doing would be url-encoded variables, which will show up in a form similar to this:
test
My guess is that it is using Array#join.
You could try something like
:test => #test.join( ',' )
and then parse the string in your controller. But it is somewhat error prone if the user enters the same character you chose as delimiter.
But, assuming the linked page is also served by Rails, I think the best solution would be to use the flash area to store the results on the server
flash[ :submitted_params ] = params;
and in the controller for the linked page
old_params = flash[ :submitted_params ] || {}

Resources