How to do route constraints in Rails 4 - ruby-on-rails

This is not working:
get '/' => 'addresses#show', :constraints => Subdomain
lib/subdomain.rb:
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.subdomain != 'www'
end
end
this route is just ignored...
thank you

Solution:
the specified route has to go before
root to: 'home#index'

This worked perfectly only you need to add subdomain.rb in you routes manually
get '/' => 'addresses#show', :constraints => Subdomain
lib/subdomain.rb:
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.subdomain != 'www'
end
end
Add in routes.rb
require 'subdomain'
And yes the specified route has to go before
root to: 'home#index'

Related

How to remove subdomain from root path in Rails

I want to remove the subdomain from root path.
I tried adding :subdomain => false to the root command in routes.rb file without success: when I enter manually a subdomain in the URL, the subdomain stays and will not be removed.
Example:
my root is => lvh.me:3000
enter subdomain manually => xyz.lvh.me:3000 and hit enter then it remains the same
This is what I tried already in my routes.rb file, without success:
root :to => 'home#show', :subdomain => false or
root :to => 'home#show', :constraints => { :subdomain => false }, via: [:get]
write this in application controller. this will work.
before_action :check_subdomain
def check_subdomain
unless company_signed_in?
if request.subdomain.present? && params[:controller] == "companies/registrations" && params[:action] == "new"
redirect_to root_url, subdomain: false
end
end
end
According to this comment on rails github, in Rails >= 4 you need to use constraints to obtain this. Try this:
constraints subdomain: false do
root to: 'home#show'
end
#dgilperez: your code works great, but I need to change in application controller too, Yes, I found the solution, I just updated with
before_action :check_subdomain
def check_subdomain
unless company_signed_in?
if request.subdomain.present? && params[:controller] == "companies/registrations" && params[:action] == "new"
redirect_to root_url, subdomain: false
end
end
end

Subdomain based resources in Rails

I am looking for a simple way to replace all my routes matching mydomain.com/resources/xx by xx.mydomain.com with Rails 4.
Would anyone have an idea to do that easily and that would work with nested resources as well?
Thanks, Joris
Constraints
What you're looking for is constraints in your routes, specifically that you're looking to use one to determine whether you have a subdomain that you can access
There are a number of resources on how to achieve this:
Basecamp-style subdomains by DHH
Subdomains Railscast
The bottom line is that you'll probably have to create a custom subdomai constraint, which you can then use the standard routing structure for:
#lib/subdomain.rb
class Subdomain
def self.matches?(request)
if request.subdomain.present? && request.subdomain != 'www'
account = Account.find_by username: request.subdomain
return true if account # -> if account is not found, return false (IE no route)
end
end
end
#config/routes.rb
constraints(Subdomain) do
get "/", to: "controller#action"
resources :posts #-> subdomain.domain.com/posts
...
end
The above is untested - I also found the following with Rails' documentation:
#lib/subdomain.rb
class Subdomain
def initialize
#accounts = Account.all
end
def matches?(request)
if request.subdomain.present? && request.subdomain != 'www'
#accounts.include?(request.subdomain)
end
end
end
#config/routes.rb
constraints: Subdomain.new do
get "/", to: "controller#action"
resources :posts #-> subdomain.domain.com/posts
...
end
Here how I have done it before in a Rails 3 app:
constraints :subdomain => /ambassador/ do
namespace(:influencer, :path => '/') do
root :to => 'home#index'
match 'home' => 'sweepstakes#index', :as => :influencer_home
resources :sweepstakes
resources :associates
resources :widgets
resources :sessions
resources :reports do
resource :member
end
match 'faq' => 'info#faq'
end
end
Be sure to put this block towards the top of the routes.rb file so it takes precedence.
You can of course nest your resources in here like normal.

Exclude all other resources from subdomain in Rails

I have a Rails 4.0 app with that allows users to access blogs through subdomains. My routes currently look like this:
match '', to: 'blogs#show', via: [:get, :post], constraints: lambda { |r| r.subdomain.present? && r.subdomain != 'www' }
resources :foobars
Now, when I navigate to somesubdomain.example.com I am indeed taken to the showaction of the blogs controller action, as expected.
When I navigate to example.com/foobars I can access the index action of the foobars controller, as expected.
However, I only get a behavior I do not desire:
When I navigate to somesubdomain.example.com/foobars, I can still access the the index action of foobars controller.
Is there a way to limit or exclude all resources that I do not specifically allow for a particular subdomain (i.e. somesubdomain.example.com/foobars will not work unless otherwise specified).
Thanks!
If you need to define a specific subdomain to exclude from a set of routes you can simply do this (uses negative lookahead regex):
# exclude all subdomains with 'www'
constrain :subdomain => /^(?!www)(\w+)/ do
root to: 'session#new'
resources :foobars
end
Or similarly, to define a specific subdomain to include a set of routes you could do this:
# only for subdomain matching 'somesubdomain'
constrain :subdomain => /^somesubdomain/ do
root to: 'blog#show'
resources :foobars
end
Another approach would be to define the constraint match in a class (or module) and then wrap all routes within constraints block:
class WorldWideWebSubdomainConstraint
def self.matches?(request)
request.subdomain.present? && request.subdomain != 'www'
end
end
App::Application.routes.draw do
# All "www" requests handled here
constraints(WorldWideWebSubdomainConstraint.new) do
root to: 'session#new'
resources :foobars
end
# All non "www" requests handled here
root to: 'blogs#show', via: [:get, :post]
end

Overwrite root route in rails 4 for a certain subdomain

I'd like so overwrite my root :to => redirect("/projects") route if the subdomain is equal to "www" or is just "". This means if the subdomain is "www" or "" the app should use my website#index controller/action.
At the moment I got this setup:
class Subdomain
def self.match(r)
r.subdomain == "www" || r.subdomain == ""
end
end
.....
# website
scope :constraints => lambda { |request| Subdomain.match(request) } do
get '/' => 'website#index'
get "/help" => "website#help", as: "help"
get "/about" => "website#about", as: "about"
get "/signup" => "website#signup", as: "signup"
# post "/signup" => "website#signup_account"
end
root :to => redirect("/projects")
If I access www.satisfy.dev/help or satisfy.dev/help everything works fine. If I access www.satisfy.dev/ or satisfy.dev/ the root_path (/projects) is in use. I thought the get '/' => 'website#index' should be more important than the root_path since it's above the root_path.
Hope somebody has a hint for me!
I tried treating the routes as "get" requests and had more success.
See here:
Multiple 'root to' routes in rails 4.0

Rails 3.1 Multitenancy routes

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

Resources