在单个应用程序上处理多个域的Rails路由

时间:2022-01-25 11:00:36

I've been unable to find a workable solution to this problem, despite several similar questions here and elsewhere. It seems likely that this question hasn't been answered for Rails 3, so here goes:

我一直未能找到一个可行的解决这个问题的办法,尽管这里和其他地方有几个类似的问题。似乎这个问题在Rails 3中还没有得到解答,因此,如下所示:

I have an application that currently allows users to create their own subdomain that contains their instance of the application. While in Rails 2 you were best served using the subdomain-fu gem, in version 3 it's dramatically simpler, as per the Railscast -- http://railscasts.com/episodes/221-subdomains-in-rails-3.

我有一个应用程序,它允许用户创建自己的子域,其中包含应用程序的实例。在Rails 2中,您最好使用subdomain-fu gem,而在版本3中,它非常简单,如Railscast——http://railscasts.com/episode des/221-subdomains-inrails3所示。

That's good stuff, but I also want to provide the option for users to associate their own domain name with their account. So while they might have http://userx.mydomain.com, I'd like them to choose to have http://userx.com associated as well.

这是很好的东西,但是我也想为用户提供将他们自己的域名与他们的帐户相关联的选项。因此,尽管他们可能有http://userx.mydomain.com,但我希望他们也选择将http://userx.com关联起来。

I found a few references to doing this in Rails 2, but those techniques don't appear to work anymore (particularly this one: http://feefighters.com/devblog/2009/01/21/hosting-multiple-domains-from-a-single-rails-app/).

我在Rails 2中找到了一些这样做的参考,但是这些技术似乎不再起作用了(特别是这个技术:http://feedfighters.com/devblog/2009/01/21/host-multidomains-from- a-single-rails-app/)。

Can anyone recommend a way to use routes to accept an arbitrary domain and pass it along to a controller so I can show the appropriate content?

有人能推荐一种使用路由接受任意域并将其传递给控制器的方法吗?

Update: I've gotten most of an answer now, thanks to Leonid's timely response, and a fresh look at the code. It ultimately required an addition to the existing Subdomain code that I was using (from the Railscast solution) and then adding a bit to routes.rb. I'm not all the way there yet but I want to post what I have so far.

更新:由于Leonid的及时响应,以及对代码的全新理解,我现在已经得到了大部分的答案。它最终需要对我正在使用的现有子域代码(来自Railscast解决方案)进行添加,然后向routing .rb添加一点。我还没有完全做到这一点,但我想把我到目前为止所拥有的东西发布出来。

In lib/subdomain.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

I've added the second class in imitation of the first, which is known working. I simply add a condition that ensures that the incoming domain is not the one for which I'm hosting the main site.

我模仿第一课,增加了第二课,这是大家都知道的。我只是添加了一个条件,确保传入域不是我托管主站点的域。

This class is used in routes.rb:

这门课在日常生活中使用。

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

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

Here, I'm prepending the existing subdomain code (again, it's working fine) with a stanza to check for the Domain. If this server responds to that domain and it's not the one under which the main site operates, forward to the specified controller.

在这里,我将使用节预先挂起现有的子域代码(同样,它工作得很好)来检查域。如果此服务器响应该域,并且它不是主站点所操作的域,则转发给指定的控制器。

And while that appears to be working, I don't quite have the whole thing working yet, but I think this particular problem has been solved.

虽然这看起来是可行的,但我还没有把所有的事情都做好,但是我认为这个特殊的问题已经解决了。

1 个解决方案

#1


89  

It's actually simpler in Rails 3, as per http://guides.rubyonrails.org/routing.html#advanced-constraints:

在Rails 3中,它实际上更简单,如http://guides.rubyonrails.org/rout. html#advanced-constraint:

1) define a custom constraint class in lib/domain_constraint.rb:

1)在lib/ domain_constrainn中定义一个自定义约束类。

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

2)使用新的块语法在路由中使用类

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

#1


89  

It's actually simpler in Rails 3, as per http://guides.rubyonrails.org/routing.html#advanced-constraints:

在Rails 3中,它实际上更简单,如http://guides.rubyonrails.org/rout. html#advanced-constraint:

1) define a custom constraint class in lib/domain_constraint.rb:

1)在lib/ domain_constrainn中定义一个自定义约束类。

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

2)使用新的块语法在路由中使用类

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