Маршрутизация Rails 3 и несколько доменов

Мое приложение позволяет людям создавать портфели. Я хотел бы, чтобы они могли подключить свой домен к своему портфолио.

Так что somedomain.com будет показывать/портфолио/12, someotherdomain.com будет показывать/портфолио/13 и так далее. Но я не хочу перенаправления. Я хочу, чтобы пользователь увидел somedomain.com в URL-адресе браузера.

Как мне это сделать?

Хорошо, я нашел это решение:

match "/" => "portfolio#show", 
  :constraints => { :domain => "somedomain.com" }, 
  :defaults => { :id => '1' }

Поскольку у меня не так много настраиваемых доменов, на данный момент это нормально, но возникает вопрос: как сделать эту динамику, читать данные домена и идентификатора из db?

Ответ 1

Во-первых, вы должны добавить поле в модель портфеля для хранения домена пользователя. Убедитесь, что это поле уникально. Добавление индекса в поле в вашей базе данных также было бы разумным.

Во-вторых, установите корень для перехода к действию portfolios#show, как вы это делали, но без ограничений.

Затем в методе PortfoliosController#show выполните следующую проверку:

if params[:id]
  @portfolio = Portfolio.find(params[:id])
else
  @portfolio = Portfolio.find_by_domain(request.host)
end

После этого остается только убедиться, что ваш собственный домен не вызывает действие portfolio#show. Это можно сделать с помощью ограничения, которое вы использовали ранее, но теперь с вашим собственным доменом. Обязательно поместите эту строку в route.rb над строкой для действия portfolio#show, так как приоритет основан на порядке создания.

Ответ 2

Хорошо, предположим, что вы владеете yourdomain.com и используете его как свою домашнюю страницу для своего приложения. И любое другое доменное имя, подобное somedomain.net, отображается на страницу портфолио.

Прежде всего, в вашем routes.rb вам нужно поймать yourdomain.com и отобразить его везде, где есть ваша домашняя страница, чтобы он выделялся из остальной толпы.

root :to => "static#home", :constraints => { :domain => "yourdomain.com" }

Затем вам нужно поймать любой другой корень в любом домене и переслать его на PortfoliosController

root :to => "portfolios#show"

Имейте в виду, что эта строка будет проверяться только в том случае, если предыдущая строка не соответствует.

Затем в вашем PortfoliosController найдите запрошенное портфолио по его домену, а не по идентификатору.

def show
  @portfolio = Portfolio.find_by_domain(request.host)
  …
end

Конечно, вы можете избавиться от исключения ActiveRecord::RecordNotFound в случае, если домен отсутствует в вашей базе данных, но оставьте это для другого обсуждения.

Надеюсь, что это поможет.

Ответ 3

Кажется, объект request недоступен для файла routes.rb без каких-либо исправлений.

Есть некоторые плагины, которые делают его доступным, но большинство из них, похоже, устарели. Здесь request_routing, похоже, с самыми последними датами фиксации, поэтому он будет наиболее актуальным. Хотя я сомневаюсь, что он будет работать с Rails 3.0 из коробки, это начало, и его не так уж сложно портировать.

Ответ 4

Ваши пользователи могут настроить DNS-переадресацию CNAME так, чтобы запросы на theirdomain.com попадали на your_app.com/portfolio/12.