Specify a route without subdomains - ruby-on-rails

I'm running Rails 3.0.17.
I currently have the following defined in my routes:
constraints :subdomain => "" do
get 'faq' => 'static_pages#faq'
end
The problem is that it allows any faq url with a subdomain (e.g. anysubdomain.mypage.com/faq)to route to the faq page when I only want the url without a subdomain (mypage.com/faq) to route to the faq page.
Any tips/insights?
Thank you in advance.

In your routes.rb
constraints SubdomainConstraint.new do
get 'faq' => 'static_pages#faq'
end
In your lib/
class SubdomainConstraint
def self.matches?(request)
request.subdomain.blank?
end
end

Related

Separate Domain for Namespaced Routes in Rails 4

I'm working on a Rails 4 app. One part of the app is a customer portal that has to be accessed from a separate domain.
I have everything working fine by navigating to domain.com/cp. The routes use namespaced controllers:
namespace :cp do
get :dashboard, to: 'dashboard#index', path: ''
...
end
How should I set up DNS records and change the routes definition so that another domain cpdomain.com points to domain.com/cp properly (no redirecting).
Thanks.
This answer can be useful for the rails routes problem:
Rails routing to handle multiple domains on single application
Shortened:
1) define a custom constraint class in lib/domain_constraint.rb:
class DomainConstraint
def initialize(domain)
#domains = [domain].flatten
end
def matches?(request)
#domains.include? request.domain
end
end
2) use the class in your routes with the new block syntax
constraints DomainConstraint.new('mydomain.com') do
root :to => 'mydomain#index'
end
root :to => 'main#index'
or the old-fashioned option syntax
root :to => 'mydomain#index', :constraints => DomainConstraint.new('mydomain.com')

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

Rails 3 - How to escape from subdomain route to the normal route?

I've worked on making a multiple subdomains feature for my E-commerce website. So far, I've made it possible to assign a ':subdomain' attribute for every user and display their sites on like 'subdomain.example.com'.
But, I cannot return to 'example.com' from 'subdomain.example.com' because the 'root_path' leads to not 'example.com' but 'subdomain.example.com'.
routes.rb file:
constraints(Subdomain) do
match "/" => 'contributors#show'
end
root :to => "items#index"
The Subdomain class comes from 'domains.rb' file below.
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.subdomain != "www"
end
end
contributors#show
<%= link_to 'Home', root_path # this leads to contributor#show. wanna make it to index#show. %>
Any help is welcome. Thanks.
Have you tried root_url(:subdomain => false)? This strips the link of the subdomain and should do what you want.
Rails takes the first matching path defined in the routes.rb file. If you are on the subdomain the constraint matches and match "/" matches as root path.
Try move "root :to => 'items#index'" to the top of your routes.rb file.

Force a route to exit a subdomain in Rails 3.2

I'm struggling with exiting out of a subdomain back up to the root domain in Rails 3.2.
Say I have a blog with a dashboard. Each user has a subdomain at username.blog.com. Each user also has a dashboard at blog.com/dashboard.
If a user manually types in username.blog.com/dashboard, I want them to be redirected to blog.com/dashboard.
I've tried using subdomain => false in my routes, but it seems to be of no use. I also tried a matcher underneath the domain scope, but that also didn't work. Any help would be greatly appreciated!
Relevant routes.rb follows.
resource :dashboard, :controller => 'dashboard', :subdomain => false
scope '/', constraints: lambda { |r| r.subdomain.present? && r.subdomain != 'www' } do
get '/' => 'feed#show'
end
root :to => 'dashboard#show', :subdomain => false
I would keep that logic outside the routing.
I would use dashboard_url instead of dashboard_path in my views / controllers.
I would put something like this in my ApplicationController
def dashboard_url(options={})
options[:subdomain] = false
super(options)
end

Rails Restful Routing and Subdomains

I wondered if there were any plugins or methods which allow me to convert resource routes which allow me to place the controller name as a subdomain.
Examples:
map.resources :users
map.resource :account
map.resources :blog
...
example.com/users/mark
example.com/account
example.com/blog/subject
example.com/blog/subject/edit
...
#becomes
users.example.com/mark
account.example.com
blog.example.com/subject
blog.example.com/subject/edit
...
I realise I can do this with named routes but wondered if there were some way to keep my currently succinct routes.rb file.
I think that subdomain-fu plugin is exacly what you need.
With it you will be able to generate routes like
map.resources :universities,
:controller => 'education_universities',
:only => [:index, :show],
:collection => {
:all => :get,
:search => :post
},
:conditions => {:subdomain => 'education'}
This will generate the following:
education.<your_site>.<your_domain>/universities GET
education.<your_site>.<your_domain>/universities/:id GET
education.<your_site>.<your_domain>/universities/all GET
education.<your_site>.<your_domain>/universities/search POST
The best way to do it is to write a simple rack middleware library that rewrites the request headers so that your rails app gets the url you expect but from the user's point of view the url doesn't change. This way you don't have to make any changes to your rails app (or the routes file)
For example the rack lib would rewrite: users.example.com => example.com/users
This gem should do exactly that for you: http://github.com/jtrupiano/rack-rewrite
UPDATED WITH CODE EXAMPLE
Note: this is quickly written, totally untested, but should set you on the right path. Also, I haven't checked out the rack-rewrite gem, which might make this even simpler
# your rack middleware lib. stick this in you lib dir
class RewriteSubdomainToPath
def initialize(app)
#app = app
end
def call(env)
original_host = env['SERVER_NAME']
subdomain = get_subdomain(original_host)
if subdomain
new_host = get_domain(original_host)
env['PATH_INFO'] = [subdomain, env['PATH_INFO']].join('/')
env['HTTP_X_FORWARDED_HOST'] = [original_host, new_host].join(', ')
logger.info("Reroute: mapped #{original_host} => #{new_host}") if defined?(Rails.logger)
end
#app.call(env)
end
def get_subdomain
# code to find a subdomain. simple regex is probably find, but you might need to handle
# different TLD lengths for example .co.uk
# google this, there are lots of examples
end
def get_domain
# get the domain without the subdomain. same comments as above
end
end
# then in an initializer
Rails.application.config.middleware.use RewriteSubdomainToPath
This is possible without using plugins.
Given the directory structure app/controllers/portal/customers_controller.rb
And I want to be able to call URL helpers prefixed with portal, i.e new_portal_customer_url.
And the URL will only be accessible via http://portal.domain.com/customers.
Then... use this:
constraints :subdomain => 'portal' do
scope :module => 'portal', :as => 'portal', :subdomain => 'portal' do
resources :customers
end
end
As ileitch mentioned you can do this without extra gems it's really simple actually.
I have a standard fresh rails app with a fresh user scaffold and a dashboard controller for my admin so I just go:
constraints :subdomain => 'admin' do
scope :subdomain => 'admin' do
resources :users
root :to => "dashboard#index"
end
end
So this goes from this:
site.com/users
to this :
admin.site.com/users
you can include another root :to => "{controller}#{action}" outside of that constraint and scope for site.com which could be say a pages controller. That would get you this:
constraints :subdomain => 'admin' do
scope :subdomain => 'admin' do
resources :users
root :to => "dashboard#index"
end
end
root :to => "pages#index"
This will then resolve:
site.com
admin.site.com
admin.site.com/users
Ryan Bates covers this in his Railscast, Subdomains.

Resources