I've written an application that uses a subdomain per user account to segregate environments. All this is working fine, except I have one issue. I can't get both www and "" to have a different root path than all other subdomains.
For all account subdomains, I have a root page of:
root :to => "applications#index"
I need this to be the root page for all subdomains except for a blank subdomain of "" and then "www". For www, I have this in the routes:
constraints(:subdomain => "www") do
root :to => "promos#index"
end
What I'm struggling with, is getting it so "" will also use promos#index as the root path. When it's not the root path, mywebsite.com sends them to the applications#index, which requires a login. Something I don't want users to see on a first visit.
Is there anyway to modify this code to also include mywebsite.com to have the different root? I've tried things like duplicating the code with "", but this tends to mess up all other subdomains, regardless of order. Below is the in of my routes file:
constraints(:subdomain => "www") do
root :to => "promos#index"
end
root :to => "applications#index"
You can use an object that implements 'matches?' to do some real custom stuff. Below we'll set applications#index if you are a customer subdomain, and send you to promo#index if you're not
In your routes:
Yourapp::Application.routes.draw do
constraints(SubDomain) do
root :to => "applications#index"
end
root :to => "promo#index"
...
end
and then the Subdomain matcher file:
config/initializers/subdomain.rb
class SubDomain
def self.matches?(request)
case request.subdomain
when 'www', '', nil, #admin/api/etc could also go here
false
else
true
end
end
end
subdomain.rb can also live in lib (if it's being auto-loaded)
Related
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')
I have a Rails 3.1 multi-tenancy app with a domain that I'll call mydomain.com. With this I would like to create the following routes but keep coming unstuck
default root for www.mydomain.com and mydomain.com should go to a controller called home or similar
default root for *.mydomain.com (except www) should go to a sesions/new route
default root for *.mydomain.com (except www) when logged in will go to a dashboard controller or simialar
Can anyone help with a way of achieving this?
This is pretty similar to what you're looking for: http://maxresponsemedia.com/rails/setting-up-user-subdomains-in-rails-3/.
Edit
It appears that the link is now dead (which is why we should post more than just links!), but I was able to find it in the WayBackMachine. Here are the code examples that it had.
First, we define a couple of constraints for subdomains and the root domain:
# /lib/domains.rb
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.subdomain != "www" && request.subdomain != ""
end
end
class RootDomain
#subdomains = ["www"]
def self.matches?(request)
#subdomains.include?(request.subdomain) || request.subdomain.blank?
end
end
Then, in our routes.rb, we direct the subdomains to a websites controller, but any requests to domains related to the main site get sent to the static pages that are configured for the app.
# config/routes.rb
# a bunch of other routes...
# requiring the /lib/domains.rb file we created
require 'domains'
constraints(Subdomain) do
match '/' => 'websites#show'
end
constraints(RootDomain) do
match '/contact_us', :to => 'static_pages#contact'
match '/about', :to => 'static_pages#about'
match '/help', :to => 'static_pages#help'
match '/news', :to => 'static_pages#news'
match '/admin', :to => 'admin#index'
end
I've created a devise user model. There are 2 types of user:
customer
admin
I've accomplished bij creating two 'normal' models: customer and admin. These two models are inheriting from the user model, like so:
class Customer < User
Does anyone know how I can setup a root path per type of user. I want something like this:
authenticated :customer do
root :to => "customer/dashboard#index"
end
authenticated :admin do
root :to => "admin/dashboard#index"
end
UPDATE:
I've solved the problem:
root :to => "pages#home", :constraints => lambda { |request|!request.env['warden'].user}
root :to => 'customer/dashboard#index', :constraints => lambda { |request| request.env['warden'].user.type == 'customer' }
root :to => 'admin/dashboard#index', :constraints => lambda { |request| request.env['warden'].user.type == 'admin' }
although an old question, there is no answer and it could be useful for others.
In rails 3.2 (I have never tested it with anything lower) you can do this in your routes.rb file
authenticated :admin_user do
root :to => "admin_main#index"
end
then have your normal root route further down.
This however, doesn't seem to work in rails 4 as it gives Invalid route name, already in use: 'root' (ArgumentError)(as I have just found out and was searching for a solution when I came across this question), if I figure out a way of doing it in rails 4 I will update my answer
Edit:
Ok so for rails 4 the fix is pretty simple but not so apparent right off the bat. all you need to do is make the second root route a named route by adding an as: like this:
authenticated :admin_user do
root :to => "admin_main#index", as: :admin_root
end
this is documented here but note that it seems like only a temporary fix and so is subject to change again in the future
What you could do is have a single root path, say home#index and in the corresponding controller action perform a redirect depending on their user type.
For instance:
def index
if signed_in?
if current_user.is_a_customer?
#redirect to customer root
elsif current_user.is_a_admin?
#redirect to admin root
end
end
end
Using after_sign_in_path_for should be appropriate. So add this to your application_controller.rb:
def after_sign_in_path_for(resource)
if resource.type == 'customer'
your_desired_customer_path
else
your_desired_admin_path
end
end
I'm trying to set up a subdomain network for my domain. In my config/routes.rb I have:
constraints :subdomain => /network.*/ do
...
# Root
match '/' => 'questions#index'
match '' => 'questions#index'
root :to => 'questions#index', :as => 'network_root'
end
root :to => 'frontend#home'
However, sometimes when I access network.domain.com (in production) it shows the root for the whole application (frontend#home). Accessing the subdomain in development works as expected.
EDIT: I've just noticed that requests to the app root (domain.com/) and subdomain root (network.domain.com/) do not get logged in my production.log. Any other page loads work as expected.
Is it possible to dynamically change the path from which controllers are used? Ryan Bates showed how to change the view_paths here: http://railscasts.com/episodes/269-template-inheritance
I'm making a CMS where a user can create a site and enter their own subdomain. I'd like "/" to point to "public#welcome" if there's no subdomain, but if there is a subdomain, I want it to point to "sites/public#welcome".
I'm using Rails 3.1 if that makes any difference.
You should be able to solve this situation using constraints if I'm not mistaken (which I might, since I haven't actually tried the following yet):
constraints(:subdomain => /.+/) do
root :to => 'sites/public#welcome'
end
root :to => 'public#welcome'
I figured it out:
constraints(:subdomain => /.+/) do
scope :module => "sites" do
root :to => 'public#welcome'
end
end
root :to => 'public#welcome'
Now when a user visits "/" Sites::PublicController will be used if a subdomain exists, but just PublicController if no subdomain exits. Adding scope :module => "sites" do...end keeps my routes file simplistic and manageable.