0

我为 Rails 应用程序中的路线设置了 RESTful 设置,使用文本永久链接作为资源的 ID。

此外,还有一些特殊的命名路由与命名资源重叠,例如:

# 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在数据库中创建新记录时,我想验证生成的永久链接是否特殊 URL 重叠。

如果用户尝试创建一个名为specialsnew-in-stock什至是普通 Rails RESTful 资源方法(如newor )的产品edit,我希望控制器查找路由配置,在模型对象上设置错误,新记录的验证失败,而不是保存它。

我可以硬编码一个已知非法永久链接名称的列表,但这样做似乎很麻烦。我更喜欢挂钩到路由以自动完成。

(控制器和型号名称更改以保护无辜并更容易回答,实际设置比此示例更复杂)

4

3 回答 3

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
于 2009-07-14T00:59:13.600 回答
0

您可以使用原本不存在的路线。这样,如果有人为标题选择保留字,它不会有任何区别。

map.product_view '/product_view/:permalink', :controller => 'products', :action => 'view'

在您看来:

product_view_path(:permalink => @product.permalink)
于 2009-07-14T01:09:23.667 回答
0

出于这样的原因,最好自己显式管理 URI,并避免意外暴露您不希望的路由。

于 2009-07-21T21:13:12.507 回答