How to set a url routing in Rails? - ruby-on-rails

I want to set this routing:
http://localhost:3000/sites/search/www.google.com
My config/routes.rb
resources :sites, only: [:index] do
collection do
get 'search/:url', to: 'sites#search'
end
end
Routes:
GET /v1/sites/search/:url(.:format) v1/sites#search {:format=>:json}
Controller
def search
#url = params[:url]
end
But when I access from URI
http://localhost:3000/sites/search/www.google.com
Got
{
"status": 404,
"error": "Not Found",
"exception": "#<ActionController::RoutingError: No route matches [GET] \"/sites/search/www.google.com\">",
"traces": {
"Application Trace": [],

A . in a url has a specific meaning, and hence can't be used directly. To handle all possible URLs in your queries, you should encode the urls before sending them in your query parameters. So
http://localhost:3000/sites/search/www.google.com
will become
http://localhost:3000/sites/search/www%2Egoogle%2Ecom
Edit:
There's actually a better solution that is more Railsy. By default, Rails expects the . to be a separator in your URL. However Rails allows you to define the format expected for your parameters using constraints.
So if you update your route definition by adding a regex constraint for the url parameter,
get 'search/:url', to: 'sites#search', constraints: { url: /.*/ }
you should now be able to handle even URLs like,
http://localhost:3000/sites/search/www.google.com

Related

How to strip whitespace from url before routes in rails

We have callbacks being issued against urls in our rails app with spaces.
Example problem URL:
www.example.net/my_collection/my_endpoint%20
The route config:
resources :my_collection do
collection do
post :my_endpoint
end
end
This causes the request to not match the route for my_endpoint. Is there any setting I can change or custom code I can write to make the request match as if there was no whitespace?
You can use route globbing to capture (and potentially ignore) parts of the incoming path
resources :my_collection do
collection do
post '/endpoint(*junk)' => 'endpoints#create'
end
end

Mismatching route for rspec testing post on a singular resource

I get the error no routes matches even tho in rake routes I have:
... POST /todo/:todo/todo_comments(.:format)
and in my rspec I have
post :todo_comments, params: { todo_id: 1 }
It sounds like your routes are defined as:
resources :todos do
resources :todo_comments
end
In a controller spec (type: :controller), you need to specify the action name in the controller that handles the request. In this case, that's :index:
post :index, params: { todo_id: 1 }
If you're in a request spec (type: :request), on the other hand, it requires the URL to request instead, which you can build using a routing helper:
post todo_todo_comments_path(1)
# or, without the helper:
post "/todos/1/todo_comments"
Note that these forms don't explicitly name the :todo_id parameter, because it will be extracted from the route.

How can I route a subdomain to rails app in routes.rb?

I have a url https://www.openhub.net which is my rails 4.2.7 app. I have a separate subdomain on another system which is https://code.openhub.net/. If you clink on the second link, this will reroute you to a discontinued page. What's hosting the code.openhub.net url is going to be decomissioned and will be rerouted to openhub.net. So what I'm trying to do is that when someone tries to go to code.openhub.net my rails app that has the openhub.net will serve a static page. The problem is that I can't conceptualize how this will work. For example, here is a snippet of rails documentation under routing.
3.9 Request-Based Constraints
You can also constrain a route based on any method on the Request object that returns a String.
You specify a request-based constraint the same way that you specify a
segment constraint:
get 'photos', to: 'photos#index', constraints: { subdomain: 'admin' }
You can also specify constraints in a block form:
namespace :admin do
constraints subdomain: 'admin' do
resources :photos
end
end
Request constraints work by calling a method on the Request object
with the same name as the hash key and then compare the return value
with the hash value. Therefore, constraint values should match the
corresponding Request object method return type. For example:
constraints: { subdomain: 'api' } will match an api subdomain as
expected, however using a symbol constraints: { subdomain: :api } will
not, because request.subdomain returns 'api' as a String.
I understand what the document is saying but when I try to put this code into practice, I'm stumped. Here is my routing.rb file:
get '???', to: '???', constraints: { subdomain: 'code' }
I understand that the subdomain constraint portion of the url will be code but will the get and to be? How do I know will go under get? Do I simply substitute get code.openhub.net which will route to a CodeController#index? Has anyone tried to do something like this before? From the documentation I see that the request object has an original_url method that I can call. Is there perhaps a way I can make use of this? Any help would be greatly appreciated.
As a sidenote, I noticed that subdomain is not a property of the request object outlined here Rails Request Object
This should work:
get '/', to: 'code#index', constraints: { subdomain: 'code' }
That will route requests to https://code.openhub.net/ to the the index method in your CodeController.
However, the URL will still say https://code.openhub.net/. If you don't want that, you might try a redirect, like this:
get '/', to: redirect('https://www.openhub.net/'), constraints: { subdomain: 'code' }

Rails routes: param value a single dot

I am trying to add an route to rails application:
scope 'some_scope' do
resources :some_resource, path: :resource, param: :name, constraints: { name: %r{.+} }, only: %i(update), format: false do
put '/', as: :update, on: :collection, to: 'friendship_tags#update_collection'
end
end
This works fine for all kind of url values, e.g. http://www.google.com, but considering dot-only values it seems completely broken.
the considered route is:
PUT /some_scope/some_resource/:name
they is also another route called: (this is route inside of block)
PUT /some_scope/some_resource
Now what happens is:
When I call
PUT /some_resource/.
Rails somehow interprets this as second url. (PUT /some_scope/some_resource)
When I call
PUT /some_scope/some_resource/..
There is an exception for routing:
ActionController::RoutingError (No route matches [PUT] "/some_scope")
When I call
PUT /some_scope/some_resource/...
Then everything is working fine.
Can someone help me out? I currently do not find a solution for that?

Redirecting a route with a format in routes.rb

I want to redirect a request to another url.
The target URL has this route:
get 'conversion_tracker/:website_url', controller: 'conversion_trackers',
action: 'show', website_url: /.*/, defaults: {format: :json}
Notice the format. It accepts a website url as a parameter. I.e. foo.com. This causes the problem in the redirect, because the route no longer knows that it should treat the foo.com as a single parameter. I guess it checks for com as a single parameter.
This is the redirect code I have right now:
get 'conversion_tracker/:website_url', to: redirect {|params, req|
"/api/extern/conversion_tracker/%{website_url}?access_token=#{params[:access_token]}"}
I then get this error:
bad URI(is not URI?): /api/extern/conversion_tracker/%{website_url}.html?access_token=
The redirect url is correct if I look at my URL in the browser:
http://localhost:3000/api/conversion_tracker/foo.com?access_token=b97b7064c4e41f226027c6cd715569d9
It just seems to be the issue with the format.
Thanks!
I had a similar problem trying to redirect images, try something like this...
get 'conversion_tracker/:website_url.:website_dom',
constraints: { website_url: /.+/, website_dom: /(com|net|org)/ },
to: redirect {|params, req| "/api/extern/conversion_tracker/%{website_url}.%{website_dom}?access_token=#{params[:access_token]}"}

Resources