単一のアプリケーションで複数のドメインを処理するためのRailsルーティング


90

ここや他の場所でいくつかの同様の質問があるにもかかわらず、私はこの問題の実行可能な解決策を見つけることができませんでした。Rails 3ではこの質問に回答されていない可能性が高いため、次のようにします。

現在、ユーザーがアプリケーションのインスタンスを含む独自のサブドメインを作成できるようにするアプリケーションがあります。Rails 2では、subdomain-fu gemを使用するのが最適でしたが、バージョン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 /)。

ルートを使用して任意のドメインを受け入れ、それをコントローラーに渡して適切なコンテンツを表示する方法を誰かが推奨できますか?

更新:Leonidのタイムリーな応答とコードの見直しのおかげで、私は今ほとんどの答えを得ています。最終的には、(Railscastソリューションから)使用していた既存のサブドメインコードに追加してから、routes.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

最初のクラスを模倣して2番目のクラスを追加しました。これは、動作することが知られています。着信ドメインがメインサイトをホストしているドメインではないことを保証する条件を追加するだけです。

このクラスはroutes.rbで使用されます:

require 'subdomain'
constraints(Domain) do
  match '/' => 'blogs#show'
end

constraints(Subdomain) do
  match '/' => 'blogs#show'
end

ここでは、既存のサブドメインコードの前に、ドメインをチェックするためのスタンザを追加しています(これも正常に機能しています)。このサーバーがそのドメインに応答し、メインサイトが動作しているドメインではない場合は、指定されたコントローラーに転送します。

それは機能しているように見えますが、まだすべてが機能しているわけではありませんが、この特定の問題は解決されたと思います。


1
編集してくれてありがとう、アーロン。私は今、まったく同じ状況に取り組んでいます。フォローアップの質問として、転送されているドメインをサーバーに受け入れさせるにはどうすればよいですか?.confファイルの設定だと思いますが、どうなるかわかりません。どんな助けでもいただければ幸いです!
デッドワード2011

アーロン、私はあなたと一緒です。同じことをしたいです。しかし、私はドメインをハードコーディングしたくありません。ゾーンファイルやWebサーバーを再起動せずに、すべてプログラムで実行したいと思います。
マイケルKマディソン

1
マイケル、あなたは問題をひっくり返す必要があります。ホストまたはサブドメインの制約を使用して、アプリケーション専用のルート(サインアップなど)を明示的に宣言およびハードコーディングしてから、メインルートを「任意のドメインまたはサブドメイン」として扱います。その場合、現在のドメインまたはサブドメインを検索して適切な顧客にマッピングするのは、コントローラーの責任です。
ジャスティンフランス語

回答:


95

http://guides.rubyonrails.org/routing.html#advanced-constraintsによると、Rails3では実際にはもっと簡単です。

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')

6
この答えは私にははるかに簡単に思えます。
Jared

7
これは素晴らしい解決策です。開発環境ではどのように機能しますか?
スーパールミナリー2012

2
@superluminary開発用にローカルドメインを設定した場合(たとえば、経由/etc/hosts)、完全に正常に機能します。
Leonid Shevtsov 2012

7
注:Powをローカルで使用し、mydomain.com.devがある場合request.domainは、.com.devを返します。に変更request.domainするrequest.hostと、完全に機能します。
Eric Muyser 2013年

2
これを機能させるには、名前のないルートを作成する必要があることがわかりました。そうしないと、Invalid route name, already in use: 'root'エラーが発生します...これを行うには、ルートを次のように変更しましたroot :to => 'mydomain#index', as: nil
Just Lucky Really

5

Rails 5では、ルートでこれを簡単に行うことができます。

constraints subdomain: 'blogs' do
  match '/' => 'blogs#show'
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.