Ruby on Rails - Passing parameters to set in url - ruby-on-rails

this maybe is an usual and easy ask to answer but Im new in this.
I have my route and view asociated to my webtool ready and working, the route is like this "mysite.com/calculator". Its about some charts which change their values depends of choices in some levers (1 up to 4). I need to add the functionality to navigate at some url like "mysite.com/calculator/1113231" where the numbers are the choices preselected.
If i can do some like that I'll need to get the numbers and set the levers by JS i think.
Some advise and/or example of how to do this?

# everything in parenthesis after the path
# helper is added as a hash to the URL
# parameters
calculator_path(number1: 80085, number2: 58008)
...will translate to
# parameters added to a URL is noted
# by the '?' followed by each parameter
# assigned and it's value
/calculator?number1=80085&number2=58008
Then you can pull the params down in your controller
first_number = params[:number1]
second_number = params[:number2]
If you want to add a dynamic value, use a variable that gets assignment from somewhere else in your code....
calculator_path(x: #rdm_num_1, y: #rnd_num_2)

Related

How to get an organized search URL result with slashes orders (/)?

I want a search section on the "index" from books_controller with some filter options from different authors, categories and other attributes. For example, I can search for a category "romance" and max pages = 200. The problem is that I'm getting this (with pg_search gem)
http://localhost:3000/books?utf8=%E2%9C%93&query%5Btitle%5D=et&button=
but I want this:
http://localhost:3000/books/[category_name]/[author]/[max_pages]/[other_options]
In order that if I want to disable the "max_pages" from the same form, I will get this clean url:
http://localhost:3000/books/[category_name]/[author]/[other_options]
It'll work like a block that I can add and remove.
What is the method I should use to get it?
Obs: this website, for example, has this kind of behavior on the url.
Thank you all.
You can make a route for your desired format and order. Path parameters are included in the params passed to the controller like URL parameters.
get "books/:category_name/:author/:max_pages/:other_options", to: "books#search"
class BooksController < ApplicationController
def search
params[:category_name] # etc.
end
end
If other options is anything including slashes, you can use globbing.
get "books/:category_name/:author/:max_pages/*other"
"/books/history/farias/100/example/other"
params[:other]# "example/other"
So that gets you the basic form, now for the other you showed it could just be another path since the parameter count changed.
get "books/:category_name/:author/*other_options", to: "books#search"
params[:max_pages] # nil
If you have multiple paths with the same number of parameters, you can add constraints to separate them.
get "books/:category_name/:author/:max_pages/*other", constraints: {max_pages: /\d+/}
get "books/:category_name/:author/*other"
The Rails guide has some furth information, from "Segment Contraints" and "Advanced Constraints": http://guides.rubyonrails.org/routing.html#segment-constraints
If the format you have in mind does not reasonably fit into the provided routing, you could also just glob the entire URL and parse it however you wish.
get "books/*search"
search_components = params[:search].split "/"
#...decide what you want each component to mean to build a query
Remember that Rails matches the first possible route, so you need to put your more specific ones (e.g. with :max_pages and a constraint) first else it might fall through (e.g. and match the *other).

Routes and query strings magic in Rails

So, I recently saw this code:
<%= link_to "Index", plays_path(id: 1) %>
1) I did not know that the index path or the plays_path took arguments. The URL doesn't have any named parameters and so I didn't think you could.
2) I read about query strings but the docs aren't great.
ActionView UrlHelper
There is no usage of the word query strings. How can you just pass any hash to a path in rails and have the params be available in the following controller? What is going on here?
You're exactly correct. Any parameters you pass in to URL / path helpers (which are not part of a named route, such as :id) will be available as parameters within your controller.
The Rails Routing Guide talks a bit about parameters and is always a good resource for how to best utilize additional parameters passed through a _url or _path helper.
All of the path helpers take a hash of arguments on the end. They're passed as extra parameters in the query string. For instance: plays_path(id: 1) will (likely) generate /plays?id=1. You can append a whole mess of them on the end as in user_path(user, active_user: 5, secure: 1, other_thing: 'happy') where user is an instance of User with id 30, would generate /user/30?active_user=5&secure=1&other_thing=happy. Most of the time these are GET parameters.

Custom Rails 4 Routes containing "/"

I have a method that generates a random url ending and a get path that looks like
/path/var1/var2
The only problem is that some of those generated values for var2 have a "/" in them. So if var 2 is "h4rd/erw" rails reads it as
/path/var1/h4rd/erw
or
/path/var1/var2/var3
rails thinks that this is another parameter of the route and i keep get the error
No route matches.
I have thought of setting up the generated value for var2 to not include "/"s or possibly putting a wildcard in the route if that's possible like /path/var1/*. What would be the best solution for this?
You can use route globbing:
get '/path/var1/*var2', to: 'controller#action'
Let's say the request went to /path/var1/h4rd/erw. Then in the controller action, the value of params[:var2] would be h4rd/erw.
I would make sure that the values are always escaped.
string = "my/string"
=> "my/string"
CGI.escape(string)
=> "my%2Fstring"
So your url will be like
/path/var1/h4rd%2Ferw
and it will go to the right controller with the right variables set.
Rails will automatically unescape the values of parameters in the controller "params" variable, so by the time you're dealing with the value in the controller the slash will be back in the string.
The only remaining question is when to do the escaping. If you pass the value as an argument to a path helper then rails should escape it automatically for you, like so:
link_to "Here", my_route_path(:foo => "bar")

rails passing parameter from view to a different controller as a string

Im trying to pass a parameter (a file path : eg. user/lauren/tools/) from a view in RAILS to another different controller using RUBY. I want to use the file path (as a string) to be matched with a regular expression. To do that, right now Im using the params [:parameter] method as follows in the controller action where Im setting the variable instance:
#variable = /^.+\/[^\/]+$/.match(params[:name]).to_s ---where :name is the parameter passed from view
Right now, I dont get any output when I try to display that in the corresponding view of that controller....im guessing its the params [:name] method I need to replace or modify?
Id really appreciate views on this...thanks!
While your server is running open a new terminal window and type rails console. This will let you see what your variables actually contain. You can type params and see what the hash has in it and see why your regex is failing. It sounds to me like you are trying to match your path, not your params.

How can I preserve querystring values across requests in Ruby on Rails?

I'm coming up against one of those moments working with Rails when I feel that there must be a better way than what I'm ending up with.
I have four querystring parameters that I want to preserve across requests through various parts of a rails app - different controllers and actions, some rendered via javascript - so that the user ends up at a URL with the same querystring parameters that they started with.
I'm finding it hard to believe that the best way is through hidden form fields and manually adding the params back in as part of a redirect_to, or using session vars for each - it just seems to un-rails like.
Does anyone know of a better way to manage this?
Thanks!
In cases like this, I'll often use a helper function to create urls based on the current set of params. In other words, I'd define this:
def merge_params(p={})
params.merge(p).delete_if{|k,v| v.blank?}
end
And then use it with url_for to create the urls for your forms and links. If you need to modify and of the params, just pass them into the merge:
# url for the current page
url_for(merge_params)
# url for a different action
url_for(merge_params(:controller => 'bar', :action => 'bar'))
# et cetera
url_for(merge_params(:action => 'pasta', :sauce => 'secret'))
This'll preserve existing params plus whatever overrides you merge in.
If you want to always preserve certain parameters accross every generated URL, you can implement a default_url_parameters method in your app.
This is poorly documented, but mentioned in the Rails 18n Guide
Implement in your application_controller.rb:
def default_url_options(*args)
super.merge(
:foo = params[:foo],
:bar = params[:bar]
)
end
Now every URL generated by Rails will include the current request's values for foo and bar (unless a url is being generated that specifies those specifically to be something else).
Please note this is not a rails solution but works for me in 80% cases. This is how I am able to achieve this with jQuery, obviously not the best approach. And I am unable to make it work past 2nd level of links:
function mergeGPS(){
var lat = getParam('lat');//localStorage.getItem('lat');
var lng = getParam('lng');//localStorage.getItem('lng');
if(lat == null || lng == null){return false;}
var links = jQuery("a");
jQuery.each(links, function(y, lnk){
//debugger;
var uri = jQuery(lnk).attr('href') + "?lat="+lat+"&lng="+lng;
jQuery(lnk).attr('href',uri);
//debugger;
})
}
function getParam(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
mergeGPS needs to be called on page load.

Resources