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

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' }

Related

Rails 6: Catch all route constraint not working

I placed a catch all route at the bottom of my route file. Annoyingly, Active Storage requests are also directed to the same action. I don't want that.
I have read this on SO and this issue on Github that suggest adding a constraint to the route.
Rails.application.routes.draw do
#...
get "/*slug" => "profiles#show",
param: :slug,
as: "profile",
contraints: lambda { |req|
req.path.exclude? "rails/active_storage"
}
end
However, this isn't working for me. ActiveStorage requests are still going to profiles#show. What is wrong with my constraint? Have I missed anything obvious?
You have a typo.
It should be constraints: instead of contraints:.

Ruby - A request route with a wildcard doesn't work

Could someone suggest why these 2 routes aren't the same:
get('/:id/' => 'outlets/play#show', :as => :listen, constraints: { id: /thetrack-a123-bay7623/ } )
get('/:id/' => 'outlets/play#show', :as => :listen, constraints: { id: /thetrack-.*/ } )
What I'm trying to achieve is only want that route outlets/play#show to be used when there is an :id that begins with thetrack.
I've found that if I explicitly use those characters its fine i.e. without thetrack in the route it doesnt use that route. However if I use thetrack-.* it still goes into the outlets/play#show route despite thetrack not being present in my request.
Any ideas?
I've tried other regex patterns e.g.
thetrack-.+
thetrack-.+-.+
thetrack-.*-.*
with no luck
If what you are trying to do is route any request /:id/ with ID starting with thetrack- to outlets/play#show, then your configured route should work:
get '/:id/', to: 'outlets/play#show', as: :listen, constraints: { id: /thetrack-.*/ }
Here are some example paths that will route to outlets/play#show using this wildcard:
/thetrack-
/thetrack-a123
/thetrack-a123-bay7623
/:id/ is quite broad reaching. Check that you have not got any other conflicting routes. i.e. another route at root level /:something/ that could be catching the other requests where thetrack- is not specified.

Rails root permalink routing

In Rails, the standard routing to objects is nested to a Model's name, example.com/model/object_id.
Is it anyhow possible to access objects without the Model part, so example.com/object_id shadowly accesses example.com/model/object_id?
Rails includes routes like you said. You can add constraints to determine object_id is integer or string.
get '/:id', to: 'articles#show', constraints: { id: /^\d/ }
This is for more information about routes constraint.
What you are first describing are the RESTful routes provided by the resources template in the rails router.
You can define different routes in the config/routes.rb file.
And for resources, you can provide a path option, where you can define a path.
resources :models, path: "/"
Will provide models resources at the route path. So a GET request to "/" would fire the "models#index" action and "/1/edit" would delegate to "models#edit"

Stop rails subdomain from triggering on *everything*

My site has some pages, such as example.com/about
I have also created an API for my app at api.example.com.
# API
namespace :api, path: '/', constraints: { subdomain: 'api' } do
scope format: true, constraints: { format: 'json' } do
get 'posts/latest', to: 'posts#latest'
get 'posts/:id', to: 'posts#show'
end
end
# Pages
get 'about' to: 'pages#about'
get 'contact', to: 'pages#contact'
The problem is, now my /about page is working on my api subdomain.
api.example.com/about should definitely not work like that, and should trigger a 404.
What I really want to do is wrap the entire rest of my routes file in constraints: { subdomain: nil } but I want to know the "Rails Way" to do this.
Thanks!
What I really want to do is wrap the entire rest of my routes file in constraints: { subdomain: nil } but I want to know the "Rails Way" to do this.
This is the Rails way.
A typical Rails app will just listen to a socket and not care about domains. Usually your webserver will handle the mapping between domains/IP addresses and internal application sockets (e.g. Apache VirtualHost).
When the webserver passes an HTTP request to the application, Rails then is only interested in everything but the (sub-) domain, unless configured otherwise.

ROR route with parentheses in constraint

I'm trying to create a rails route for movies (on the root path) that has parentheses containing the movie's year in it.
E.g. Men in black => "/men-in-black-(1997)"
My route is:
resources :movies,
path:'/',
only:[ :index, :list, :show ],
constraints: { id: /[A-Za-z0-9-]+\(\d{4}\)/ }
When I use this route (movie_path(Movie.first)), I get
"ActionController::RoutingError: No route matches: ..."
When I change the route constraint to:
constraints: { id: /[A-Za-z0-9-]+\\\(\d{4}\\\)/ }
the route works when using the url routing helper. However, the route doesn't work for the reverse mapping (e.g. taking "/men-in-black-(1997)" and routing it to the correct action/controller). When I run (from console):
Rails.application.routes.recognize_path("/men-in-black-(1997)")
I get the same routing error:
ActionController::RoutingError: No route matches
The problem seems to be associated to how rails escapes regex's in routing. For escaping with \( the object-to-route map fails, but url-to-route works. But when escaping with \\\( it is the opposite.
Anyone have any tips or experience with this?
As a workaround hack you could try:
constraints: { id: /[A-Za-z0-9-]+(\\\(\d{4}\\\)|\(\d{4}\))/ }
That is, make the constraint accept either, if it accepts one in one case and the other in the other case.
Which is to say: that's weird, I have no idea why Rails would do that or how to fix it ;)
Well I don't have a lot of experience writing regex constraints, but you could always do a wildcard route and then sanitize in the controller.
match 'movies/*movie' => 'movie#action'
This will give you access to a :movie param with all the characters input

Resources