2010-09-07 92 views
16

我想知道是否有任何插件或方法允许我转换资源路由,使我可以将控制器名称作为子域名。Rails Restful路由和子域名

例子:

map.resources :users 
map.resource :account 
map.resources :blog 
... 

example.com/users/mark 
example.com/account 
example.com/blog/subject 
example.com/blog/subject/edit 
... 

#becomes 

users.example.com/mark 
account.example.com 
blog.example.com/subject 
blog.example.com/subject/edit 
... 

我知道我可以命名路由做到这一点,但不知道是否有某种方式来保持我目前简洁的routes.rb文件。

+2

我为此添加了100个代表奖金 - 我遇到了类似的困境,所以一个可行的答案会很棒。 – Jeriko 2010-09-20 12:00:46

+0

哪个版本的Rails? 2.x或3? – tommasop 2010-09-24 09:51:54

+0

在我的情况下,2.3,尽管jeriko现在值得更多的关注。 – mark 2010-09-24 10:49:55

回答

3

做到这一点是写一个重写请求头一个简单的机架中间件库的最佳方式以便您的Rails应用获取您期望的url,但从用户的角度来看,url不会更改。这样,您就不必对您的Rails应用程序的任何更改(或路由文件)

例如机架的lib将改写:users.example.com => example.com/users

这创业板应该做的正是你:http://github.com/jtrupiano/rack-rewrite

的代码示例

注意更新:这是快速写入,没有经过测试的,但应该设置你在正确的道路上。另外,我还没有检查出机架重写的宝石,这可能使这个更简单

# your rack middleware lib. stick this in you lib dir 
class RewriteSubdomainToPath 

    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    original_host = env['SERVER_NAME'] 
    subdomain = get_subdomain(original_host) 
    if subdomain 
     new_host = get_domain(original_host) 
     env['PATH_INFO'] = [subdomain, env['PATH_INFO']].join('/') 
     env['HTTP_X_FORWARDED_HOST'] = [original_host, new_host].join(', ') 
     logger.info("Reroute: mapped #{original_host} => #{new_host}") if defined?(Rails.logger) 
    end 

    @app.call(env) 

    end 

    def get_subdomain 
    # code to find a subdomain. simple regex is probably find, but you might need to handle 
    # different TLD lengths for example .co.uk 
    # google this, there are lots of examples 

    end 

    def get_domain 
    # get the domain without the subdomain. same comments as above 
    end 
end 

# then in an initializer 
Rails.application.config.middleware.use RewriteSubdomainToPath 
+0

这对我来说最有意义,因为重点在于安宁。如果你可以详细说明一下,也许有一个代码示例,我会给你赏金。这种方法会对cookie有任何潜在的问题吗? – Jeriko 2010-09-27 09:58:48

+0

更新了代码示例。就您的Rails应用程序而言,Cookie应该没问题,因为所有请求都会到达相同的基本域。除非您试图为每个用户维护不同的Cookie。 – Nader 2010-09-27 22:04:34

+0

该死 - 看来在我可以奖励给你之前,赏金已经过期了。不知道它是否完全丢失,或者如果有什么我可以做的恢复它,会发现.. – Jeriko 2010-09-28 10:10:20

5

我认为subdomain-fu插件是exacly你所需要的。 有了它,你将能够产生像

map.resources :universities, 
    :controller => 'education_universities', 
    :only => [:index, :show], 
    :collection => { 
     :all => :get, 
     :search => :post 
    }, 
    :conditions => {:subdomain => 'education'} 

此路由将产生如下:

education.<your_site>.<your_domain>/universities GET 
education.<your_site>.<your_domain>/universities/:id GET 
education.<your_site>.<your_domain>/universities/all GET 
education.<your_site>.<your_domain>/universities/search POST 
+0

嗨伊戈尔,谢谢你的回复。我看了subdomainfu,但问题是它有效地添加一个名称空间作为子域名,而不是使用控制器名称,这正是我所希望的。在你的例子中,我希望放弃教育并将大学(控制器名称)作为子域名。 – mark 2010-09-07 12:19:13

+0

Hello Mark,现在我有同样的问题,那就是我所做的。我创建了命名空间教育,参数为:name_prefix =>''和:path_prefix =>''。在这个命名空间中,你可以做任何你想做的事,我在里面有几个额外的命名空间。但是对于其中的每条路线,您应该添加:conditions => {:subdomain =>'education'}。我不知道,如何写得更好,但我认为它运作良好。如果你愿意,请联系我,我会告诉你。 – 2010-09-09 07:24:05

0

瑞恩·贝茨包括这在他的Railscast,Subdomains

+1

对不起Yasky,Railscast并没有真正解决宁静的子域问题,而且它最终有点含糊。虽然不是我的-1。 – Jeriko 2010-09-27 09:55:44

3

这可以不使用插件。

鉴于目录结构app/controllers/portal/customers_controller.rb 我希望能够调用URL佣工portal前缀,即new_portal_customer_url。 此URL只能通过http://portal.domain.com/customers访问。 然后......这样使用:

constraints :subdomain => 'portal' do 
    scope :module => 'portal', :as => 'portal', :subdomain => 'portal' do 
    resources :customers 
    end 
end 
2

正如ileitch提到的,你可以做到这一点没有额外的宝石是非常简单的实际。

我有一个新的用户脚手架和我的管理仪表板控制器标准的新的Rails应用程序,所以我只是去:

constraints :subdomain => 'admin' do 
    scope :subdomain => 'admin' do 
     resources :users 

     root :to => "dashboard#index" 
    end 
end 

所以这正好从这个:

  • site.com /用户

这样:

  • admin.site。com/users

您可以包含另一个根:to =>“{controller}#{action}”,该约束和作用域可以被称为页面控制器。这将让你这样的:

constraints :subdomain => 'admin' do 
    scope :subdomain => 'admin' do 
     resources :users 

     root :to => "dashboard#index" 
    end 
end 

root :to => "pages#index" 

这将然后解析:

  • site.com
  • admin.site.com
  • admin.site.com/users