我希望有一个rails路由,如果给定的id存在则触发,但如果不存在则返回到进一步的路由匹配。
具体来说,我希望在我的网站的根级别有促销代码。因此,您可以转到foo.com/save87
或foo.com/xmasspecial
,它会将其视为促销代码,但如果您转到不在那里的促销代码(foo.com/badcode
),那么该路线将不匹配,rails将继续沿着路由列表。
在理想的世界中,我会在routes.rb
文件中执行以下操作:
get '/:promo_id' => 'promos#show, constraints => lambda { Promo.exists?(promo_id) }
我知道上面的代码,没有约束,可以作为foo.com/*
的全能,如果我把它作为路由文件中的最后一行,它会工作。不幸的是,这会导致foo.com/badcode
'找不到promocode'错误,而不是正常的'找不到路线'错误。
那么,有没有办法完成我想要完成的任务?这是在Rails 3中,供参考。
编辑:澄清一点 -
foo.com/save87
代替foo.com/promo_codes/save87
)foo.com/widget_deluxe
,foo.com/widget_extreme
等。我必须确保促销代码和小部件品种之间没有冲突,但这很容易在其他地方处理。答案 0 :(得分:4)
在一个理想的世界里,我在我的routes.rb文件中做了类似的事情:
没办法。在Rails
World中,此功能应该在控制器内部。
在控制器中,您可以执行类似
的操作def show
if Promo.exists?(promo_id)
#do something
else
raise ActionController::RoutingError.new('Not Found')
end
end
<强>更新强>
使用路线,你可以做这样的事情
constraints(lambda { |req| Promo.exists?(req.params["promo_id"]) }) do
get '/:promo_id' => 'promos#show
end
请注意,此约束将使用与模式/:promo_id
匹配的每个请求(e.q。/users
,/faq
)查询数据库。为避免不必要的数据库查询降低网站性能,您应尽可能将此规则添加到routes.rb
的末尾。
答案 1 :(得分:0)
使用此路由逻辑,对应用程序的每个请求都会在转到其他路由之前对促销代码进行额外搜索。我建议您查看您的业务案例并考虑使用Promo控制器。如果你必须做路线,这样的事情会起作用,但我会把它放在最后,以便它首先进入你的常规路线。
get '*', to: 'promos#show'