Rails Routing having a URL in the query string - ruby-on-rails

So I need to hit a url like mydomain.com/proxies/www.msn.com in order to fulfill some ajax requests for an API
In my route I have
get "/proxies/:url" => "proxies#get"
and I in the controller I have
url_contents = Net::HTTP.get(URI.parse(params[:url]))
which if i put /proxies/www i get
undefined method `request_uri' for #<URI::Generic:0x3f89508 URL:www>
if i put /proxies/www.msn.com
I get
No route matches [GET] "/proxies/www.msn.com"

You have two separate problems here:
You're trying to treat a URL without a scheme as an HTTP URL.
Your /proxies route won't match :urls with dots and slashes the way you're expecting it to.
For the first one, you'll have to add the schema manually:
url = 'http://' + params[:url]
content = Net::HTTP.get(URI.parse(url))
For the second one, you can use a splat-route to deal with embedded slashes and :format => false to keep Rails from trying to treat .com, for example, as a format:
get '/proxies/*url' => 'proxies#get', :format => false
If you use :url, Rails will see embedded slashes as component separators and that's probably not what you want. Without the the :format => false, Rails will try to interpret .X (for any X) as a format (just like .html, .json, ...) rather than as part of the URL.

This is applicable for rails-2
The problem is with the dot(.) I guess. Ive tried something like below and it worked.
#routes.rb
map.get_proxy 'proxies/:url', :controller => "Proxies", :action => "get", :requirements => { :url => /.*/ }
#view file
#Here dot(.) are needed to replace with its encoded string %2E
<%= link_to 'Get The Site', get_proxy_url('www.msncom') %>
#Proxies Controller
#After receiving the url the %2E need to conovert to dot(.) again.
url_contents = Net::HTTP.get(URI.parse('http://'+params[:url]))
modified as stated by #mu.

match '/proxies/:url' => 'proxies#get', :as => :proxies_get

Related

Managing URL Parameters in Rails

Right now I am finding routing and URL constructing within rails to be semi-confusing. I have currently matched the following for tags that are passed in when displaying/filtering data.
match '/posts/standard/' => 'posts#standard'
match '/posts/standard/:tags' => 'posts#standard', :as => :post_tag
match '/posts/standard/:tags' => redirect { |params| "/posts/standard/#{params[:tags].gsub(' ', '+')}" }, :tags => /.+/
However, now I want to add a 'skill' parameter that can only take one state; however, I am very confused by how I want to construct this within my URL. I cannot simply have...
match '/posts/standard/:tags/:skill' => 'posts#standard', as => post_tag, as: => post_skill
So, I am very confused by this at this point, does Rails offer any type of help for constructing URL's?
One way is to just keep your main route
match '/posts/standard/:tags' => 'posts#standard', :as => :post_tag
and handle the additional URL params as params. The url would look like:
/posts/standard/1?skill=something
and it is easy enough to inject the additional params, such as by
link_to post_tag_path(:skill=> 'something')
and your controller would then do
def standard
if params[:skill] == 'something'
...
else
...
end
end
Also, not sure about this, but your first line in your routes 'match '/posts/standard/' => 'posts#standard' may catch all of your routes since there is a match. If this is the case, simply move it to after the first line.

Escaping elements in a URI Ruby On Rails

I have a rails app that I am trying to do a get request with co-ordinates in...
I have a route in my routes.rb like this:
map.connect 'feeds/get/:location', :controller => "feeds", :action => "get"
I can send a string consisting of alphanumeric characters fine, but I need to send co-ordinates in a string in the URI as a get request:
51.896834,0.878906.
So, I escaped the string like so, and append it to my URI.
http://thisisnottheurl.net/feeds/get/51%2E896834%2C0%2E878906.xml
however it looks like rails automatically unescapes the string before the controller and gives me this routing error in the log:
ActionController::RoutingError (No route matches "/feeds/get/51.896834,0.878906.xml" with {:method=>:get}):
How do I stop rails escaping this string (with routes?) so that it can be read in the controller?
I looked at using the match function in routes.rb with regex, but that is rails 3 only...
The only real way I can think of doing this would be as follows, give the route a name as follows:
map.connect 'feeds/get', :controller => "feeds", :action => "get", as: 'get_feeds'
Then you would have a named route helper get_feeds_path, which you could then pass in location and a format as follows:
get_feeds_path(:location => '51.896834,0.878906', :format => 'xml')
What might be an even better idea however, is if you passed in two params, one for each of the coordinates.
get_feeds_path(:x_location => '51.896834', :y_location => '0.878906', :format => 'xml')
Then, the params hash passed to the controller should have a params[:x_location] and a params[:y_location] which you can manipulate to your liking.

Generating a form that passes multiple parameters

I have the following in my routes.rb
map.diff 'posts/:id/diff/:from/:to', :controller => "posts",
:action => "diff", :conditions => { :method => :get }
And I have the following in my view file.
- form_tag(diff_path(), :method => :get) do
= text_field_tag(:from, "")
= text_field_tag(:to, "")
= hidden_field_tag(:id, #post.id)
= submit_tag("Submit")
I would like to generate a form that submits something like "http://example.com/posts/3/diff/13/18", but it fails. How can I make such a form?
I need to pass parameters for diff_path(), but I don't know how to do that. I don't even know if this is possible with form_tag.
The error message:
diff_url failed to generate from {:action=>"diff", :controller=>"posts"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: ["posts", :id, "diff", :from, :to] - are they all satisfied?
To my knowledge, what you're trying to accomplish can't be done with just an HTML form. The reason being that the form will only know how to submit traditionally via GET and POST. It has no knowledge of the structure of the URL.
You get that error message because the :id, :from and :to parameters are required to form the both you want, so when you call diff_path() it freaks out.
Personally, I would advise you not to use the URL structure you're planning on - however I'm not totally clear on what this page is going to display. Regardless, if the :from and :to parameters are algorithmic input and not resource identifiers, I would avoid this structure.
That said, if you do want to implement this, you would either have to implement a redirect from rails or javascript.
Rails method
#some_controller.rb
redirect_to diff_path(:from => params[:from], :to => params[:to])
Javascript (jQuery) method
$(function() {
$("form#your_form_id_here").submit(function() {
window.location = "posts/" + this.id + "/diff/" + this.from + "/" + this.to;
return false;
});
});
I don't think that will work by specifying the url with that format in the form. Rails tries to create the URL to submit to when you render the page, not when you submit the form. So it is not seeing those parameters when you render the page. I would recommend creating another route
map.diff_form 'posts/:id/diff', :controller => :post, :action => :diff, :conditions => {:method => :post}
You could use the two routes side by side if you need to keep the current url format.
Why are you trying to do this in the first place? I really can't think of a good reason why this would be necessary.
Your "from" and "to" variables should probably just be normal URL parameters - i.e. /posts/:id/diff?from=X&to=Y, so that you can then retrieve them in your controller with params[:from] and params[:to]
There may be a way to make Rails work this way, but you're going to have issues with it, since Rails is emphatically not meant to work this way.
I think you can use like this
diff_path(#id,#from, #to)
where #id, #from, #to are instance variables. If dont, you can specify a hash also like
diff_path(:id=>#id,:from=>#from, :to=>#to)

url_for generates a url with current path inserted

I am generating a url in my controller accessed from the relative path "/hangouts/test", for a url on an external site (facebook). I want to use url_for and pass in params using hashes so it can escape them. The URL I want is this:
http://www.facebook.com/connect/prompt_permissions.php?api_key=6aca22e72866c7eaaedfb15be69c4b93&...
Using this, however:
url_for(:host => "www.facebook.com/connect/prompt_permissions.php?", :api_key => Facebooker.api_key, :next => test_hangouts_url, :cancel => root_url, :ext_perm => "publish_stream")
I instead get my current path of /hangouts/test thrown in there:
http://www.facebook.com/connect/prompt_permissions.php/hangouts/test?api_key=6aca22e72866c7eaaedfb15be69c4b93&...
As you can see, I don't want "/hangouts/test" to be in there - played a bit with the options in the API docs but stumped, anybody know how to use url_for without it inserting the current path? Thanks!
You shouldn't be using the hash form of url_for to generate links outside of your application.
Instead you should just be using the string version form:
url_for "http://www.facebook.com/connect/prompt_permissions.php?api_key=6aca22e72866c7eaaedfb15be69c4b93&next=#{test_hangouts_url}&cancel=#{root_url}&ext_perm=publish_stream"
url_for will use the current action controller/action/id unless the hash given to url_for contains one of those arguments. url_for will then generate a url from a route that matches the arguments given in the hash. The arguments to url_for used in the question generates a valid url, because it can match a route using the current controller/action. You will not be able to generate the url you want with the hash form of url for without matching a route. Providing a controller in the hash you give url_for should match the default routes that rails generates for you when you create an application, but that's not very DRY.
The better solution is to use a named route:
map.prompt_fb_permissions "/connect/prompt_permissions.php",
:host => "www.facebook.com", :controller => nil, :action => nil
then you can use the following in place of url_for whenever you want to generate this this url.
prompt_fb_permissions(:api_key => Facebooker.api_key, :next => test_hangouts_url,
:cancel => root_url, :ext_perm => "publish_stream")
You left out the controller parameter, which is why it's automatically adding your controller path ("/hangouts/test"), to your base host.
Try this:
url_for(:host => "www.facebook.com", :controller=> "/connect/prompt_permissions.php", :api_key => Facebooker.api_key, :next => test_hangouts_url, :cancel => root_url, :ext_perm => "publish_stream")

Ruby on Rails: Routing for a tree hierarchy of places

So we've got a legacy system that tracks places with IDs like "Europe/France/Paris", and I'm building a Rails facade to turn this into URLs like http:// foobar/places/Europe/France/Paris. This requirement is not negotiable, the number of possible levels in unlimited, and we can't escape the slashes.
Setting up routes.rb for http://foobar/places/Europe is trivial:
map.resources :places
...but http:// foobar/places/Europe/France complains "No action responded to Europe". I tried:
map.connect '/places/:id', :controller => 'places', :action => 'show'
...but this gives the same result, as apparently the :id ends at the first '/'. How do I make the ID cover anything and everything after the "places"?
Have a look at the Routing Guide for full documentation:
http://guides.rubyonrails.org/routing.html
Specifically section "4.9 Route Globbing".
But I think what you really want to do is declare your route like:
map.connect '/places/*id', :controller => 'places', :action => 'index'
Called with a URL like
/places/foo/bar/1
Yields a params[:id] => ["foo", "bar", "1"]
Which you could easily (re)join with "/" to yield the full string you want "foo/bar/1" (you will probably have to re-insert the leading slash manually.
That should get you going.
I tweaked Cody's answer above slightly to come up with this:
map.place '/places/*id', :controller => 'places', :action => 'show'
map.connect '/places/*id.:format', :controller => 'places', :action => 'show'
By using map.place instead of map.connect, Rails knows what resource we're dealing with and generated place_url, place_path etc helpers correctly.
Now, the 2nd line should work but doesn't thanks to the bug above, so here's a workaround for places_controller.rb that manually splits the ID and sets the format, defaulting to XML:
id, suffix = params[:id].join('/').split('.')
params[:format] = suffix ? suffix : "xml"

Resources