【问题标题】:Rails query parameter with same name as optional path parameter与可选路径参数同名的 Rails 查询参数
【发布时间】:2018-04-16 12:25:56
【问题描述】:

假设,我在 routes.rb 中有这段代码

get "/items/(:brand)", to: "items#index", as: :items

我无法更改此路线,因为有时我需要路径中带有品牌的网址(而不是查询中)。 我可以创建这样的路径吗:

/items?brand=TestBrand

但不是这个:

/items/TestBrand

通过路由助手?

items_path(brand: "TestBrand") 给出第二个变体。

【问题讨论】:

  • get "/items/(:brand)", to: "items#index", as: :items 是一条非常糟糕的路线,因为它违反了 RESTful 约定,并与正常的演出路线 (GET /items/:id) 产生了歧义。你为什么不能把它改成更好的东西,比如GET /brands/:brand_id/items
  • 我需要用遗留代码支持大块 :(,实际上这个代码比我的例子复杂得多
  • 那么您需要决定是否需要进行重大更改,因为现有代码实际上可能无法按预期工作。

标签: ruby-on-rails rails-routing


【解决方案1】:

这不是一个很好的解决方案,因为它违反了 RESTful 约定。

在 Rails 风格中,REST GET /resource_name/:id 映射到显示路线。在get "/items/(:brand)", to: "items#index", as: :items 的情况下,当路由器匹配请求并且第一个声明的路由将获胜时,这会产生歧义(段是项目ID 还是品牌?),这几乎是不可取的。

更好的解决方案是将其声明为嵌套资源:

resources :brands, only: [] do
  resources :items, only: [:index], module: :brands
end

    Prefix Verb URI Pattern                       Controller#Action
brand_items GET  /brands/:brand_id/items(.:format) brands/items#index

# app/controllers/brands/items_controller.rb
module Brands
  class ItemsController < ::ApplicationController
    before_action :set_brand

    # GET /brands/:brand_id/items
    def index
      @items = @brand.items
    end

    def set_brand
      @brand = Brand.find(params[:brand_id])
    end
  end
end

【讨论】:

    【解决方案2】:

    默认支持“get”中的附加参数,所以也许你可以使用

    get "/items", to: "items#index", as: :items
    

    resources :items, only: [:index]
    

    并使用您提供的路径助手:

    items_path(brand: "TestBrand")
    

    【讨论】:

    • get "/items/(:brand)", to: "items#index", as: :items 请看我的问题,我需要使用带条件参数的路由
    • 如果您需要这两种变体,请将它们添加到路由中:get "/items", to: "items#index", as: :itemsget "/items/(:brand)", to: "items#index", as: :brand_items 顺便说一句,最大的权利,它不是很 RESTfull。也许考虑改变行为会更好。
    【解决方案3】:

    回答您的问题 - 是的,您可以

    get "/items", to: "items#index", as: :items
    

    以下路由助手将创建

    items_path(brand: "TestBrand")
    #=> items?brand=TestBrand
    

    注意:

    如果您正在使用:

    recourses :items
    

    你一定已经有了这个

    【讨论】:

    • get "/items/(:brand)", to: "items#index", as: :items 我无法更改这一点,因为有时我需要路径中带有品牌的网址(不在查询中)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 2020-01-16
    • 2019-04-25
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    相关资源
    最近更新 更多