Ruby-on-rails Rails 路由以在单个应用程序上处理多个域

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4207657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:39:16  来源:igfitidea点击:

Rails routing to handle multiple domains on single application

ruby-on-railsruby-on-rails-3routingroutessubdomain

提问by Aaron Vegh

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/episodes/221-subdomains-in-rails-3

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.comassociated 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: https://feefighters.com/blog/hosting-multiple-domains-from-a-single-rails-app/).

我在 Rails 2 中找到了一些关于这样做的参考,但这些技术似乎不再起作用(尤其是这个:https: //feefighters.com/blog/hosting-multiple-domains-from-a-single-rails -应用程序/)。

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 解决方案),然后添加一些到 routes.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:

这个类在 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.

虽然这似乎奏效了,但我还没有完全完成工作,但我认为这个特殊问题已经解决。

回答by Leonid Shevtsov

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

根据http://guides.rubyonrails.org/routing.html#advanced-constraints,它在 Rails 3 中实际上更简单:

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

1) 在 中定义自定义约束类lib/domain_constraint.rb

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

回答by user3033467

In Rails 5, you can simply do this in your routes:

在 Rails 5 中,你可以简单地在你的路线中做到这一点:

constraints subdomain: 'blogs' do
  match '/' => 'blogs#show'
end