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

发布于 2025-01-10 07:57:25 字数 708 浏览 0 评论 0原文

我正在使用 Rails,并且在预订时有两种视图(客户和培训师)。我正在尝试根据当前用户是谁从索引路由到客户或培训师。

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

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

I'm using Rails and I have two views in bookings (clients and trainers). I'm trying to route from index to client or trainers depending on who is the current_user.

If I'm a client, route index to trainers
If I'm a trainer, route index to clients

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ぃ双果 2025-01-17 07:57:25

你正在向后嵌套。路由的输出实际上应该看起来更像:

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方式描述了端点返回属于其他资源的内容。这应该由 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

您可以通过重新构想该功能来实现此目的,以便链接“特定用户 URL”而不是通用 URL。例如,您可以在 Stackoverflow 的仪表板上看到这一点,该仪表板使用 https://stackoverflow.com/users/{id}/{username}

REST 理论上应该是无状态的,因此无论是谁请求,每个路径都应该返回相同的资源。但与所有规则一样,这可能会被破坏,您可以设置如下路由:

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

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

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

Devise 具有经过身份验证的路由帮助程序,可让您为经过身份验证/未经身份验证的用户设置不同的路由。例如,如果讲师被实现为不同的 Warden 范围:

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 取决于用户拥有的“角色”。

You're doing nesting backwards. And the output of your routes should actually look more like:

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

This describes RESTfully that the endpoint returns something belonging to the other resource. This should be handled by the index action - ideally of a controller designated for that purpose as each controller should only be responsible for one resource.

You could define these routes as:

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

You can implement this by reimagining the feature so that you link the "specific users URL" instead of a generic URL. You can see this for example on the dashboard here on Stackoverflow which uses https://stackoverflow.com/users/{id}/{username}.

REST is in theory supposed to be stateless so each path should return the same resource no matter who is requesting it. But like all rules this could be broken and you can set up routes like:

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

Which would return different results for the signed in user which is stateful. user here would be consider a singular resource. This is mostly useful if you need to have a significantly different represention of the resource when viewing "your own" vs "others".

To actually be able to use the "current user" from the routes the authentication system must be implemented as Rack middleware (like Devise is) and not on the controller level as almost all the "reinventing the wheel" tutorials are. Routing is Rails is implemented as Rack middeware that is run before your controller is ever instanciated.

Devise has the authenticated routing helper which lets you setup different routes for authenticated/unauthenticated users. For example if instructors are implemented as different warden scopes:

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

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

But you could also use a lambda if you only have one warden scope (the typical Devise configuration):

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

Both of these would route GET /bookings to Instructors::BookingsController#index and Students::BookingsController#indexdepending on which "role" the user has.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文