Rails Restful Routing和Subdomains

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

例子:

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文件。

最好的方法是编写一个简单的机架中间件库来重写请求标头,以便rails应用程序获得您期望的URL,但从用户的角度来看,URL不会更改。 这样您就不必对rails应用程序(或路径文件)进行任何更改

例如,机架lib将重写:users.example.com => example.com/users

这个gem应该完全适合你: http : //github.com/jtrupiano/rack-rewrite

更新代码示例

注意:这是快速编写的,完全未经测试,但应该让您走上正确的道路。 另外,我还没有检查出机架重写的gem,这可能会使这更加简单

 # 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 

我认为subdomain-fu插件非常适合你需要的东西。 有了它,你将能够生成像这样的路线

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

这将生成以下内容:

 education../universities GET education../universities/:id GET education../universities/all GET education../universities/search POST 

这可以在不使用插件的情况下实现。

给定目录结构app/controllers/portal/customers_controller.rb我希望能够调用前缀为portal URL助手,即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 

正如ileitch所提到的,你可以在没有额外gem的情况下做到这一点,实际上它非常简单。

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

 constraints :subdomain => 'admin' do scope :subdomain => 'admin' do resources :users root :to => "dashboard#index" end end 

所以这就是这样的:

  • site.com/users

对此:

  • admin.site.com/users

你可以包含另一个root:to =>“{controller}#{action}”以外的那个约束和site.com的范围,可以说是一个页面控制器。 那会让你这样:

 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

Ryan Bates在他的Railscast, Subdomains中介绍了这一点。