Ruby on Rails route for wildcard subdomains to a controller/action - ruby-on-rails

I dynamically create URLs of the form username.users.example.com:
bob.users.example.com
tim.users.example.com
scott.users.example.com
All of *.users.example.com requests should go to a particular controller/action. How do I specify this in routes.rb?
All other requests to www.example.com go to the normal list of routes in my routes.rb file.
UPDATE: I watch the railscast about subdomains and it showed the following bit of code which would seem to be exactly what I need (changed the controller and subdomain):
match '', to: 'my_controller#show', constraints: {subdomain: /.+\.users/}
The problem is it only matches the root URL. I need this to match EVERY possible URL with a *.users subdomain. So obviously I would put it at the top of my routes.rb file. But how do I specify a catch-all route? Is it simply '*'? Or '/*'?

I think, you just need to do the following :
create a class Subdomain in lib :
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.host.include?('.users')
end
end
and in your routes :
constraints Subdomain do
match '', to: 'my_controller#show'
end

You can constraint route dynamically based on some specific criteria by creating a matches? method
Lets say we have to filter sub domain of URL
constraints Subdomain do
get '*path', to: 'users#show'
end
class Subdomain
def self.matches?(request)
(request.subdomain.present? && request.subdomain.start_with?('.users')
end
end
What we are doing here is checking for URL if it start with sub domain users then only hit users#show action. Your class must have mathes? method either class method or instance method. If you want to make it a instance method then do
constraints Subdomain.new do
get '*path', to: 'proxy#index'
end
you can achieve same thing using lambda as well like below.
Instead of writing class we can also use lambdas
get '*path', to: 'users#show', constraints: lambda{|request|request.env['SERVER_NAME'].match('.users')}

Related

allow access to one page on sub-domain, and if tried accessing other pages redirect to main domain

allow access to one page(campaigns/test) on sub-domain(aap.example.com), and if tried accessing other pages redirect to main domain(example.com)
app.example.com is my sub-domain of my main domain example.com, so same rails app is running on domain and sub-domain.
I tried some solutions like adding constraints in routes file and nginx file as well, but not getting what I need.
routes.rb
constraints(Subdomain) do
match '/campaigns/:slug' => 'campaigns#show', via: [:get]
match "/cam_enquiry" => "campaigns#cam_enquiry", via: [:post]
end
and the subdomain.rb module
class Subdomain
def self.matches?(request)
case request.subdomain
when 'app', '', nil
false
else
true
end
end
end
Let me know if you need anymore details.
Define all your routes and after it define constraint for app subdomain. You need to match test route and use redirect for all other subdomain routes. Specify only blank subdomain in redirect parameters, in this case it will get all other info from request and only change subdomain to main domain
get 'campaigns/test', to: redirect(subdomain: 'app'), constraints: { subdomain: '' }
get '/campaigns/:slug', to: 'campaigns#show'
post '/cam_enquiry', to: 'campaigns#cam_enquiry'
constraints subdomain: 'app' do
get 'campaigns/test', to: 'contoroller#action'
get '/*any', to: redirect(subdomain: '')
end

How to get resource id from subdomain in Rails 4?

We're developing a conference management app and most of the resources is nested resource of conference. Now, we decided to use subdomains for conference homepages and got trouble on refactoring resources.
Current url scheme is like:
/conferences/:id/speeches
/conferences/:id/manage
We want to move /conferences/:id part to subdomain and use resources like:
conferenceid.sitename.com/speeches
conferenceid.sitename.com/manage
Here are the current routes file:
https://github.com/kodgemisi/confdeck/blob/development/config/routes.rb#L17
What's the best way to make this transition? How can we prevent current url helpers?
first lets tweak your subdomain class. the following code should be enough
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.subdomain != 'www'
end
end
then you should be able to call it in the routes with the following
constraints(Subdomain) do
resource :conference, path: "/" do
member do
get 'apply'
post 'apply' => "conferences#save_apply"
end
end
Then in your Controller you go like this:
Conference.find_by_slugged!(request.subdomain)
(i saw you use friendly id, so i think your subdomain is sluggged of the Conference.

Rails wildcard route with database lookup & multiple controllers

I have a Rails application setup where, after all of the other site routes are defined, I have a catch-all wildcard for my Users to display their Profiles on selected root-level "vanity" URLs of non-reserved paths/keywords:
get '*path' => 'profiles#show'
The Profiles controller then checks to make sure the path defines a valid Profile, otherwise redirects to root. This works fine.
What I need to do now is create a mechanism where the catch-all path could define either a Profile or a Blog, based on the database lookup of the path for the proper controller to route to.
I do not want to do a redirect ... I want to load either the Profile or Blog content on the original wildcard URL.
What are my options to go from wildcard route -> db lookup -> proper controller?
In other words, where might this logic properly go?
Thanks.
It seem like you want a route constraint that will match some pattern (regex) that defines if a path matches a route or if it tries the subsequent routes. Maybe something like this.
get '*path', :to => 'profiles#show', :constraints => { path: /blog\/.+/ }
The idea is that you must know something at the routing level, if it can be path based then the above thing will work otherwise if it needs to be more complex you can use a custom constraints class.
# lib/blog_constraint.rb
class BlogConstraint
def initialize
#slugs = Blog.pluck(:slug)
end
def matches?(request)
request.url =~ /blog\/(.+)/
#slugs.include?($1)
end
end
# config/routes.rb
YourApp::Application.routes.draw do
get '*path', :to => 'blogs#show', :constraints => BlogConstraint.new
get '*path', :to => 'profiles#show'
end

How to setup specific subdomain for rails routes?

I am trying to setup a subdomain for my site in rails. I followed to rails cast to do this.
http://railscasts.com/episodes/221-subdomains-in-rails-3?view=comments
I am having an issue. I want to state that for a specific static subdomain as a secondary homepage.
constraints(Subdomain) do
match '/' => 'static_pages#secondary_home'
end
root to: 'static_pages#home'
lib/subdomain.rb
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.subdomain.eql? "secondaryhome"
end
end
so now I expect only secondaryhome.lvh.me:3000 to point to my secondary homepage. (lvh.me is and external domain that points to localhost) .However, any subdomain I have (for instance abc.lvh.me:3000) seems to be pointing to the secondary home, while i want it to default to my primary root. What should i do?
We've done the equivalent of this:
#config/routes.rb
constraints({ subdomain: "secondaryhome" }) do
match '/' => 'static_pages#secondary_home'
end
This sets a route for lvh.me:3000 with constraint { subdomain: "secondaryhome" } - only that should work

Prevent subdomain access for html requests

I have a subdomain widgets.mywebsite.com. The only thing the subdomain does is return json on a given route. How do I prevent people/crawlers accessing my site via the subdomain whilst still keeping the route available? I would be happy to simply redirect any requests that include this subdomain to mywebsite.com but can't work out how to do it.
constraints :subdomain => 'widgets' do
namespace :widgets, :path => nil, :format => 'json' do
match 'v1' => 'v1/widgets#index'
end
end
So it sounds like you want to reverse the logic in your routes - you want to constrain the bulk of your routes so that they only resolve when the subdomain isn't equal to widgets. That's opposed to the above example, where you're making a single route only available on the 'widgets' subdomain. This is pretty straightforward.
In your config/routes.rb you can define a class before the Application.routes.draw block
class NotWidgetsRequest
def matches?(request)
request.subdomain != 'widgets'
end
end
and then you can wrap all of your routes other than the v1/widgets#index route in a
constraints NotWidgetRequest.new do
...
end
block. This will prevent these routes from resolving on widgets.mywebsite.com

Resources