rails如何区分用户/:id和用户/新路由?

时间:2018-04-17 13:20:21

标签: ruby-on-rails ruby routes

我试图了解rails如何知道两条路线之间的区别

GET /users/:id

GET /users/new

当我们输入

resources :users

我试图跟踪并理解rails源代码中的资源方法,但我并没有完全理解它。

    def resources(*resources, &block)
      options = resources.extract_options!.dup

      if apply_common_behavior_for(:resources, resources, options, &block)
        return self
      end

      with_scope_level(:resources) do
        options = apply_action_options options
        resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], options)) do
          yield if block_given?

          concerns(options[:concerns]) if options[:concerns]

          collection do
            get  :index if parent_resource.actions.include?(:index)
            post :create if parent_resource.actions.include?(:create)
          end

          new do
            get :new
          end if parent_resource.actions.include?(:new)

          set_member_mappings_for_resource
        end
      end

      self
    end

以下代码是否可以实现?

     new do
       get :new
     end if parent_resource.actions.include?(:new)
如果是的话,你能解释一下吗?

此外,如果我尝试使用相同的GET users/new格式编写另一条路线,它会重定向到GET users/:id,那么如何在不考虑之类的情况下编写另一条路由,如GET users/whatever 作为:id

以下是routes.rb

的示例

示例1:

get   '/feedbacks/:id'  => 'feedbacks#show'
get   '/feedbacks/count'     => 'feedbacks#count'

feedbacks/count重定向到/feedbacks/:id

示例2:

resources :feedbacks
get   '/feedbacks/count'     => 'feedbacks#count'

feedbacks/count重定向到/feedbacks/:id

2 个答案:

答案 0 :(得分:6)

Rails不区分,它只是搜索第一条记录,适合条件

这就是为什么new比id

生成的原因

示例1:

get '/feedbacks/count' => 'feedbacks#count'
get '/feedbacks/:id'   => 'feedbacks#show'

示例2:

resources :feedbacks do
  member do
    get '/feedbacks/count' => 'feedbacks#count'
  end
end

You can read about it here

答案 1 :(得分:1)

Rails路由基本上是在steriods上的正则表达式。它们匹配路径表达式,HTTP方法和任何其他约束。

路由按照定义的顺序具有优先级。当路由器匹配路由集合中的请求时,它会停止搜索,这就是为什么顶部的路由总是赢的原因。

如果查看resources宏的输出,您可以看到路由被排序以考虑这一点:

     Prefix Verb   URI Pattern                Controller#Action
    things GET    /things(.:format)          things#index
           POST   /things(.:format)          things#create
 new_thing GET    /things/new(.:format)      things#new
edit_thing GET    /things/:id/edit(.:format) things#edit
     thing GET    /things/:id(.:format)      things#show
           PATCH  /things/:id(.:format)      things#update
           PUT    /things/:id(.:format)      things#update
           DELETE /things/:id(.:format)      things#destroy

必须在GET /things/new之前声明GET /things/:id路线。否则它将与things#show路由匹配,并在控制器尝试查找ActiveRecord:: RecordNotFound时发出Thing id = "new"错误。

  

users /:id,那么如何编写另一条路线,如GET用户/等等   不考虑作为:id?

使用收集选项:

resources :things do
  get :foo, on: :collection
end

# same but with block syntax
resources :things do
  collection do
    get :foo
    get :bar
  end    
end

您还可以添加其他成员路由(前缀为ID):

resources :trips do
  patch :cancel
end

请注意,Rails默认为on: :member,因此您无需明确设置它。

由于resources位于顶部(yield if block_given?),这些路线将具有正确的优先级。

请参阅: