Маршрутизация Rails для обработки нескольких доменов в одном приложении
Я не смог найти работоспособного решения этой проблемы, несмотря на несколько подобных вопросов здесь и в других местах. Кажется вероятным, что на этот вопрос не было ответа для Rails 3, так что вот так:
У меня есть приложение, которое в настоящее время позволяет пользователям создавать свой собственный поддомен, который содержит их экземпляр приложения. В то время как в Rails 2 вам лучше всего использовать гем subdomain-fu, в версии 3 это значительно проще, чем в Railscast - http://railscasts.com/episodes/221-subdomains-in-rails-3.
Это хорошая вещь, но я также хочу предоставить пользователям возможность ассоциировать свое доменное имя с учетной записью. Поэтому, хотя у них может быть http://userx.mydomain.com, я бы хотел, чтобы они тоже связали http://userx.com.
Я нашел несколько ссылок на это в Rails 2, но эти методы больше не работают (особенно этот: https://feefighters.com/blog/hosting-multiple-domains-from-a-single-rails-app/).
Кто-нибудь может порекомендовать способ использования маршрутов для принятия произвольного домена и передачи его контроллеру, чтобы я мог показать соответствующий контент?
Обновление: я получил большинство ответов сейчас благодаря своевременному ответу Леонида и новому взгляду на код. В конечном итоге это потребовало дополнения к существующему коду субдомена, который я использовал (из решения Railscast), а затем добавило немного в rout.rb. Я еще не дошел, но хочу опубликовать то, что у меня есть.
В lib/subdomain.rb:
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.subdomain != "www"
end
end
class Domain
def self.matches?(request)
request.domain.present? && request.domain != "mydomain.com"
end
end
Я добавил второй класс в подражание первому, который, как известно, работает. Я просто добавляю условие, гарантирующее, что входящий домен не является тем, для которого я размещаю основной сайт.
Этот класс используется в rout.rb:
require 'subdomain'
constraints(Domain) do
match '/' => 'blogs#show'
end
constraints(Subdomain) do
match '/' => 'blogs#show'
end
Здесь я дополняю существующий код субдомена (опять же, он работает нормально) строфой для проверки домена. Если этот сервер отвечает на этот домен, а не тот, под которым работает основной сайт, перешлите к указанному контроллеру.
И хотя это, похоже, работает, у меня пока не все работает, но я думаю, что эта конкретная проблема была решена.
Ответы
Ответ 1
Это действительно проще в Rails 3, в соответствии с http://guides.rubyonrails.org/routing.html#advanced-constraints:
1) определить собственный класс ограничений в lib/domain_constraint.rb
:
class DomainConstraint
def initialize(domain)
@domains = [domain].flatten
end
def matches?(request)
@domains.include? request.domain
end
end
2) используйте класс в ваших маршрутах с новым синтаксисом блока
constraints DomainConstraint.new('mydomain.com') do
root :to => 'mydomain#index'
end
root :to => 'main#index'
или старомодный синтаксис параметров
root :to => 'mydomain#index', :constraints => DomainConstraint.new('mydomain.com')
Ответ 2
В Rails 5 вы можете просто сделать это на своих маршрутах:
constraints subdomain: 'blogs' do
match '/' => 'blogs#show'
end