代码之家  ›  专栏  ›  技术社区  ›  madlep

在Ruby on Rails中创建新资源时验证没有路由重叠

  •  0
  • madlep  · 技术社区  · 15 年前

    我在一个Rails应用程序中使用文本permalinks作为资源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 访问时对PermaLink字段进行查找。一切正常。

    但是,当创建新的 产品 数据库中的记录,我想验证生成的PermaLink 与特殊URL重叠。

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

    我可以硬编码一个已知的非法永久性名称列表,但这样做似乎很混乱。我更愿意加入路由来自动完成它。

    (控制器和模型名称更改以保护无辜者并使其更容易回答,实际设置比本例更复杂)

    3 回复  |  直到 15 年前
        1
  •  1
  •   madlep    15 年前

    好吧,这行,但我不确定它有多漂亮。主要问题是将控制器/路由逻辑混合到模型中。基本上,您可以在模型上添加一个自定义验证来检查它。这是使用未记录的路由方法,所以我不确定它会有多稳定。有人有更好的主意吗?

    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
    
        2
  •  0
  •   Hardryv    15 年前

    您可以使用不存在的路由。这样,如果有人选择保留字作为标题或不保留字,就不会有什么不同了。

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

    在你看来:

    product_view_path(:permalink => @product.permalink)
    
        3
  •  0
  •   aehlke    15 年前

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

    推荐文章