我在Rails应用程序中使用文本永久链接作为资源ID,为路由设置了RESTful设置。
此外,还有一些特殊的命名路由与命名资源重叠,例如:
# bunch of special URLs for one off views to be exposed, not RESTful
map.connect '/products/specials', :controller => 'products', :action => 'specials'
map.connect '/products/new-in-stock', :controller => 'products', :action => 'new_in_stock'
# the real resource where the products are exposed at
map.resources :products
Product
模型使用permalink_fu根据名称生成永久链接,ProductsController
在访问时对永久链接字段执行查找。一切正常。
但是,当在数据库中创建新的Product
记录时,我想验证生成的永久链接不与特殊网址重叠。
如果用户尝试创建名为specials
或new-in-stock
的产品,或者甚至是new
或edit
等正常的Rails RESTful资源方法,我希望控制器能够查找路由配置,在模型对象上设置错误,对新记录的验证失败,而不是保存它。
我可以硬编码已知的非法永久链接名称列表,但这样做似乎很麻烦。我宁愿挂钩路由来自动完成。
(控制器和型号名称已更改,以保护无辜并使其更容易回答,实际设置比此示例更复杂)
答案 0 :(得分:1)
嗯,这很有效,但我不确定它有多漂亮。主要问题是将控制器/路由逻辑混合到模型中。基本上,您可以在模型上添加自定义验证以进行检查。这是使用未记录的路由方法,所以我不确定它将来会有多稳定。有人有更好的想法吗?
class Product < ActiveRecord::Base
#... other logic and stuff here...
validate :generated_permalink_is_not_reserved
def generated_permalink_is_not_reserved
create_unique_permalink # permalink_fu method to set up permalink
#TODO feels really ugly having controller/routing logic in the model. Maybe extract this out and inject it somehow so the model doesn't depend on routing
unless ActionController::Routing::Routes.recognize_path("/products/#{permalink}", :method => :get) == {:controller => 'products', :id => permalink, :action => 'show'}
errors.add(:name, "is reserved")
end
end
end
答案 1 :(得分:0)
您可以使用原本不存在的路线。这样,如果有人为标题选择了保留字,它就没有任何区别。
map.product_view '/product_view/:permalink', :controller => 'products', :action => 'view'
在你的意见中:
product_view_path(:permalink => @product.permalink)
答案 2 :(得分:0)
出于这样的原因,自行明确管理URI是一种更好的做法,并避免意外暴露您不想要的路由。