Rails => 根据 current_user 将索引路由到两个不同的页面

Rails => routing index to two different pages depending on the current_user

我正在使用 Rails 并且我在预订方面有两种看法(客户和培训师)。我正在尝试根据 current_user.

从索引路由到客户或培训师

如果我是客户,请将索引路由至培训师 如果我是培训师,请将索引路由至客户

class BookingsController < ApplicationController
  def index

  end

  def clients
    @bookings = Booking.where(client: current_user)
    @clients = current_user.bookings.map(&:client)
  end

  def trainers
    @trainers = current_user.bookings.map(&:user)
  end

end
Rails.application.routes.draw do
  resources :bookings do
    collection do
      get "/clients", to: "bookings#clients", as: "clients"
      get "/trainers", to: "bookings#trainers", as: "trainers"
    end
    resources :shared_training_plans, except: [:new]
  end
end

您正在向后嵌套。你的路线输出实际上应该更像:

GET /instructors/1/bookings # bookings belonging to instructor 1
GET /instructors/1/clients  # clients that are associated with instructor 1
GET /students/3/bookings    # bookings belonging to student 3
GET /students/3/instructors # instructors belonging to student 3

这以 REST 方式描述了端点 return 属于其他资源的东西。这应该由 index 操作处理 - 理想情况下是为此目的指定的控制器,因为每个控制器应该只负责一个资源。

您可以将这些路线定义为:

resources :instructors do
  resources :bookings, module: :instructors
end

resources :clients do
  resources :bookings, module: :clients
end
module Instructors
  class ClientsController < ApplicationController
    # GET /instructors/1/clients
    def index 
      @instructor = Instructor.find(params[:instructor_id])
      @clients = @instructor.clients
    end
  end
end
module Clients
  class InstructorsController < ApplicationController
    # GET /clients/1/clients
    def index 
      @client = Client.find(params[:client_id])
      @clients = @client.instrucors
    end
  end
end

您可以通过重新构想该功能来实现这一点,以便您 link“特定用户 URL”而不是通用 URL。例如,您可以在使用 https://whosebug.com/users/{id}/{username}.

的 Whosebug 上的仪表板上看到这一点

REST 在理论上应该是无状态的,因此无论谁请求它,每个路径都应该 return 相同的资源。但就像所有规则一样,这可能会被打破,您可以设置如下路线:

GET /user/bookings # GET bookings for the currently signed in user

对于有状态的登录用户,return 会有不同的结果。 user 这里将被视为单一资源。如果您在查看“您自己的”与“其他”时需要具有明显不同的资源表示,这将非常有用。

为了真正能够从路由中使用“当前用户”,身份验证系统必须作为 Rack 中间件(如 Devise)实现,而不是在控制器级别实现,因为几乎所有“重新发明轮子”教程都是.路由是 Rails 作为 Rack 中间件实现的,它是 运行 在你的控制器被实例化之前。

Devise 具有 authenticated 路由帮助程序,可让您为 authenticated/unauthenticated 用户设置不同的路由。例如,如果讲师被实现为不同的监狱长范围:

authenticated :instructor do
  resource :bookings, controller: 'instructors/bookings', only: [:index]
end

authenticated :student do
  resource :bookings, controller: 'students/bookings', only: [:index]
end

但是如果你只有一个 warden 范围(典型的 Devise 配置),你也可以使用 lambda:

authenticate :user, ->{|u| u.instructor? } do
  resource :bookings, controller: 'instructors/bookings', only: [:index]
end

authenticate :user, ->{|u| u.student? } do
  resource :bookings, controller: 'students/bookings', only: [:index]
end

这两者都会将 GET /bookings 路由到 Instructors::BookingsController#indexStudents::BookingsController#index,具体取决于用户具有的“角色”。