Rails 5使用自定义操作

时间:2016-12-01 15:42:17

标签: ruby-on-rails ruby-on-rails-5

关于路由,如果我这样做:

resources :students
resources :teachers

我会得到类似的东西:

  

学生GET /学生(.:format)学生#index
  ...
  教师GET /教师(.:format)老师#index
  ...

更改为:

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

会给我:

  

学生GET /学生(.:format)用户#index
  教师GET /教师(。:format)用户#index

请注意,现在,两个资源都使用相同的控制器Users和相同的操作index。但我需要的是index资源,而不是使用相同的students操作,以students为前缀的students_index资源为前缀的teachersteachers资源。 teacher_index就像bin/rails routes

换句话说,我希望get 'students', to: 'users#students_index' 给我以下输出:

  

学生GET /学生(.:format)用户#students_index
  教师GET /教师(。:format)用户#teachers_index

我知道我也可以这样做:

MyTable

但是有一种方法可以对资源做同样的事情吗?

2 个答案:

答案 0 :(得分:0)

我认为资源助手没有办法做到这一点。你可以做什么(如果它只是你想覆盖的索引动作)是添加一个除外,像这样:

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

或者你可以重新考虑控制器的结构......祝你好运!

答案 1 :(得分:0)

有一种更好的方法可以做到这一点,因为你可能已经推测 - 继承。

# 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键的内容。