我有两个资源控制器,我使用slug来表示ID。 (friendly_id gem)。
我能够在路线上获得一个资源的显示路径,但不能同时拥有两个资源。即
root :to => 'home#index'
match '/:id' => "properties#show"
match '/:id' => "contents#show"
基本上我想要网址,
# Content
domain.com/about-us
domain.com/terms
# Property
domain.com/unique-property-name
domain.com/another-unique-property-name
无论我在顶级作品上投入什么资源。有没有办法做到这一点?
如果你能提供帮助,谢谢。
答案 0 :(得分:5)
这是未经测试的,但请尝试在路线上使用constraint
。
root :to => 'home#index'
match '/:id', :to => "properties#show",
:constraints => lambda { |r| Property.find_by_id(r.params[:id]).present? }
match '/:id', :to => "contests#show",
:constraints => lambda { |r| Contest.find_by_id(r.params[:id]).present? }
或者,您可以创建一个响应matches?
的单独类,而不是定义lambda
proc。 (我建议将这些类放入可在Rails应用程序中自动加载的单独文件中。)
# app/constraints/property_constraint.rb
class PropertyConstraint
def self.matches?(request)
property = Property.find_by_id(request.params[:id])
property.present?
end
end
# app/constraints/contest_constraint.rb
class ContestConstraint
def self.matches?(request)
contest = Contest.find_by_id(request.params[:id])
contest.present?
end
end
# config/routes.rb
root :to => 'home#index'
match '/:id', :to => "properties#show", :constraints => PropertyConstraint
match '/:id', :to => "contests#show", :constraints => ContestConstraint
不幸的是,这会产生额外的数据库查询(一次在路由中,在控制器中再次出现)。如果有人建议尽量减少这个,请分享。 :)
答案 1 :(得分:2)
此Rails引擎可以满足您的需求:
基本上,作者的方法是在他的主应用程序中安装Rails引擎。该引擎既包含一个控制器,用于处理存在的slu and,也包含一个中间件,用于过滤和弃用不存在的slu ..
他解释了为什么他在一个相当详细和有趣的blog post中采用了这种方法和其他流产的解决方案。这篇博客文章和slug引擎源代码应该足以让你自己编写和运行代码,但是如果你想要一个直接的解决方案,这个开源引擎似乎正是你正在寻找的。< / p>
答案 2 :(得分:1)
您可以在中间件
中执行此操作:
匹配'contents /:id'=&gt; “属性#秀”
匹配'properties /:id'=&gt; “内容#显示”
答案 3 :(得分:1)
您可以编写另一个控制器,它从路由器获取id并检查id是属于属性还是内容并呈现相应的视图。
match '/:id' => "router#show"
控制器将执行以下操作:
def show
@property = Property.find(params[:id])
if @property then
render 'property/show'
else
@content = Content.find(params[:id])
render 'content/show
end
end
我没有测试过这段代码,但这个想法应该可行。
答案 4 :(得分:0)
如果可能的话,我建议您以更加RESTful的方式执行此操作。基本上,您有两种不同的资源,您应该将它们分开:
match 'properties/:id' => "properties#show"
match 'contents/:id' => "contents#show"
这将为您带来许多优势。一个直接的好处是,您可以避免属性和内容的ID之间的冲突。 (请注意,friendly_id不会帮助您解决原始方案中的模型间冲突问题。)