簡體   English   中英

使用自定義操作的Rails 5路由資源

[英]Rails 5 routing resources using custom actions

關於路由,如果我做這樣的事情:

resources :students
resources :teachers

我會得到類似:

學生GET /學生(。:format)學生#index
...
教師GET /teachers(.:format)教師#index
...

更改為:

resources :students, controller: :users
resources :teachers, controller: :users

會給我:

學生GET /students(.:format)users#index
教師GET /teachers(.:format)users#index

請注意,現在,兩個資源都使用相同的控制器Users和相同的操作index 但是,我需要的不是使用相同的index動作,而是使用students資源來使用以students為前綴的動作(如students_index和以teachers為前綴的teachers資源(如teacher_index

換句話說,我希望bin/rails routes能夠提供以下輸出:

學生GET /students(.:format)users#students_index
教師GET /teachers(.:format)users#teachers_index

我知道我可以使用以下方法進行操作:

get 'students', to: 'users#students_index'

但是有一種方法可以對資源進行處理嗎?

我認為沒有辦法使用資源助手來做到這一點。 您可以執行的操作(如果僅是您要覆蓋的索引操作)是添加一個例外,如下所示:

resources :students, controller: :users, except: [:index]
resources :teachers, controller: :users, except: [:index]

然后,正如您已經建議的那樣,個人對此類操作進行索引:

get 'students', to: 'users#students_index', as: :student
get 'teachers', to: 'users#teachers_index', as: :teacher

或者您可以重新考慮控制器的結構...祝您好運!

有一種更好的方法可以做到這一點,因為您可能已經猜到了-繼承。

# app/controllers/users_controller.rb
class UsersController < ApplicationController

  delegate :singular, :plural, :param_key, to: :model_name

  before_action :set_resource, only: [:show, :edit, :update, :destroy]
  before_action :set_resources, only: [:index]

  def initialize
    @model_name = resource_class.model_name
    super
  end

  def show
  end

  def index
  end

  def new
    @resource = resource_class.new
    set_resource
  end

  def create
    @resource = resource_class.new(permitted_attributes)

    if @resource.save
      redirect_to @resource
    else
      set_resource
      render :new
    end
  end

  def edit
  end

  def update
    if @resource.update(permitted_attributes)
      redirect_to @resource
    else
      set_resource
      render :edit
    end
  end

  def destroy
    @resource.destroy
    redirect_to action: "index"
  end

  # ...

  private

  # Deduces the class of the model based on the controller name
  # TeachersController would try to resolve Teacher for example.
  def resource_class
    @resource_class ||= controller_name.classify.constantize
  end 

  # will set @resource as well as @teacher or @student
  def set_resource
    @resource ||= resource_class.find(params[:id])
    instance_variable_set("@#{singular}", @resource)
  end

  # will set @resources as well as @teachers or @students
  def set_resources
    @resources ||= resource_class.all
    instance_variable_set("@#{plural}", @resources)
  end

  def permitted_attributes
    params.require(param_key).permit(:a, :b, :c)
  end
end

# app/controllers/teachers_controller.rb
class TeachersController < UsersController
end

# app/controllers/students_controller.rb
class StudentsController < UsersController
end

# routes.rb
resources :students
resources :teachers

在命名動作和視圖時,這使您可以遵循常規的Rails約定而不是配置方法。

UsersController基類通過ActiveModel :: Naming運用了很多魔術來找出模型類和諸如命名實例變量和params鍵之類的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM