我需要路由才能使用rails app的托管和whitelabel版本。这两个版本都在相同的代码库和相同的服务器上运行,所以路由需要解决问题,但我不清楚如何实现这一点。
我正在建立一个工作委员会。每个注册的公司都可以在网站上创建自己的公司资料。如果他们获得付费高级版本,他们可以使用自己的CNAME网址,并在其子域之一上提供工作板。所有非常标准的东西。
在主网站上需要查看哪些路线
http://jobsrus.com/companies/company-name
# e.g.
http://jobsrus.com/companies/microsoft
导致诸如
之类的路线http://jobsrus.com/companies/microsoft/jobs/
http://jobsrus.com/companies/microsoft/newest
在whitelabel网站上需要查看哪些路线
该公司还可以对工作板进行白色标记,使其看起来像这样:
http://jobs.microsoft.com/jobs
http://jobs.microsoft.com/newest
澄清差异
为了澄清,两者都将提供相同的controller#action
:
http://company-domain/jobs
# and
http://jobsrus.com/companies/company-name/jobs
丑陋的路由:
最简单的路由是:
的routes.rb
resources :companies do
...
resources :jobs do
...
end
end
给出:
http://jobsrus.com/companies/microsoft/jobs
# but also
http://jobs.microsoft.com/companies/microsoft/jobs
我们希望后者是:
http://jobs.microsoft.com/jobs
如何从路线中删除第一级嵌套?
我的问题很简单。如何从路线中删除companies/company-name
嵌套级别?白标网站唯一需要的路由是:
的routes.rb
resources :jobs do
...
end
如何从路由中动态包含或排除嵌套级别?我可以使用request.host
变量来触发切换,但我不知道如何最好地激活或取消激活该嵌套层。
------编辑(和部分解决方案)-----------------------
使用@ m_x的答案我已经使用约束来创建路由。为了更好地说明问题,我还使用了一些额外的路线:
(简化为只显示:show和:index方法)
def company_resources
resources :jobs, only: [:index, :show] do
resource :applicants, only: [:index, :show] do
resource :messages, only: [:index, :show]
end
end
end
constraints host: /^(?!jobsrus\.com)/ do
company_resources
end
resources :companies, only: [:index, :show] do
company_resources
end
这在匹配传入请求方面效果很好,我们可以看到rake routes
生成我们正在寻找的匹配项:
job_applicants_messages GET /jobs/:job_id/applicants/messages(.:format) {:host=>/^(?!jobsrus\.com)/, :action=>"show", :controller=>"messages"}
job_applicants GET /jobs/:job_id/applicants(.:format) {:host=>/^(?!jobsrus\.com)/, :action=>"show", :controller=>"applicants"}
jobs GET /jobs(.:format) {:host=>/^(?!jobsrus\.com)/, :action=>"index", :controller=>"jobs"}
job GET /jobs/:id(.:format) {:host=>/^(?!jobsrus\.com)/, :action=>"show", :controller=>"jobs"}
company_job_applicants_messages GET /companies/:company_id/jobs/:job_id/applicants/messages(.:format) {:action=>"show", :controller=>"messages"}
company_job_applicants GET /companies/:company_id/jobs/:job_id/applicants(.:format) {:action=>"show", :controller=>"applicants"}
company_jobs GET /companies/:company_id/jobs(.:format) {:action=>"index", :controller=>"jobs"}
company_job GET /companies/:company_id/jobs/:id(.:format) {:action=>"show", :controller=>"jobs"}
companies GET /companies(.:format) {:action=>"index", :controller=>"companies"}
company GET /companies/:id(.:format) {:action=>"show", :controller=>"companies"}
但是,现在不再有任何规范方法来生成路线。如果我们想要创建一个指向特定公司工作指数的路线,我们必须使用不同的方法,具体取决于我们是在白标公司还是jobsrus.com
公司:
# path generator for jobs page on a whitelabel company
jobs_path
# => 'microsoft.com/jobs'
# path generator for jobs page on a company on the main site
company_jobs_path @company
# => 'jobsrus.com/companies/microsoft/jobs'
# what is actually required
company_jobs_path @company
# => 'jobsrus.com/companies/microsoft/jobs' (when on main site)
# => 'microsoft.com/jobs' (when on whitelabel)
我可以覆盖路径方法并定义一些根据host
变量切换的方法。尽管如此,rails way
这样做会很好。这支持了吗?
答案 0 :(得分:1)
在初始化程序中,定义一个常量:
YOUR_HOST = 'jobsrus.com'.freeze
然后在routes.rb中:
constraints :host => /!#{YOUR_HOST}/ do
resources :jobs
end
resources :companies do
resources :jobs
end
此处的顺序非常重要:如果request.host
与您的主机名不匹配,则第一组路由可用并在请求到达第二组之前捕获该请求。
但现在,您需要对控制器进行更改,以便它可以检索公司并相应地调整作业资源的范围(没有尝试过,请谨慎使用):
class JobsController < ApplicationController
before_filter :resolve_whitelabel
def resolve_whitelabel
if request.host != YOUR_HOST
# not safe as is, just demonstrates the idea
@client = Company.find_by_host( request.host )
@scoped_jobs = Job.where( company_id: @client.id )
else
@scoped_jobs = Job
end
end
def scoped_jobs
@scoped_jobs
end
def index
# just an example
@jobs = scoped_jobs.recent
end
end
您必须始终记住使用scoped_jobs
。
修改强>
您可以在Proc:
中“存储”某个区块routes = Proc.new do
resources :jobs
end
...然后您应该可以使用Proc
运算符将此&
转换回块:
constraints( :host => /!#{YOUR_HOST}/, &routes )
resources( :companies, &routes )
这需要进行测试,我从未在此上下文中使用它。特别要注意,Proc
充当闭包:它在创建时捕获其上下文(此范围中可用的变量等,这称为'绑定')(就像块一样) 。这可能会导致意外行为(虽然我认为在这种情况下它不重要,因为你的Proc
的范围与原始块的范围相同。)