【问题标题】:Set a before action to all member routes?为所有成员路由设置之前的操作?
【发布时间】:2014-02-10 22:51:57
【问题描述】:

在使用 Rails 4 时,我注意到它定义了一个 before_action 过滤器 set_[model],它被调用用于操作 showeditupdatedestroy

它实际上非常有用,但我认为对所有成员操作都没有它没有多大意义。毕竟,如果您正在使用成员操作,您希望对该成员进行操作,因此您需要在某个时候从数据库中恢复它。

请注意,成员操作是指在members 块中的routes.rb 上配置的操作。

是否有一种直接的方法可以做到这一点,而不列出 before_action 过滤器上的所有成员操作?

编辑:澄清一下,重点是使用一些 Rails 魔法来获取所有成员路由并生成将在 :only 中传递的数组。所以我可以做类似的事情

before_action set_model only: all_member_routes

其中all_member_routes 是一段代码,它返回我的模型的所有成员路由。

甚至更好,

before_action set_model, only_member_actions: true

【问题讨论】:

    标签: ruby-on-rails actioncontroller


    【解决方案1】:

    showeditupdatedestroy 动作正是所有成员动作。他们是唯一需要找到模型的人。

    如果您有自己的成员操作,则必须自己将其添加到列表中。

    before_action :set_item, only: [:edit, ..., :my_member_action]
    

    或者,您可以使用:except 选项排除所有不需要它的收集操作:

    before_action :set_item, except: [:index, :create]
    

    这样,如果您添加其他成员操作,您将不必更改任何内容。 就个人而言,我更喜欢明确并使用:only

    我很确定没有更简单的方法可以做到这一点,您无法自动检测所有成员操作。


    编辑

    我真的不认为你应该这样做,但是......

    您可以使用controller_name 方法访问控制器的名称。

    获取控制器相关的路由:

    routes = Rails.application.routes.routes.select { |r| r.defaults[:controller] == controller_name }
    

    那么,我认为判断一个路由是否是成员路由的最好方法是@parts数组包含:id。也许您可以找到更稳健的方法。

    所以我会这样做:

    routes.select { |r| r.parts.include?(:id) }.map { |r| r.defaults[:action] }.map &:to_sym
    

    这会给你:[:show, :preview, :my_challenges] for

     resources :users, only: [:index, :show], controller: 'accounts/users' do
       member do
         get :preview
         get :my_challenges
       end
     end
    

    class ApplicationController < ActionController::Base 
    
        def member_routes
            Rails.application.routes.routes
                .select { |r| r.defaults[:controller] == controller_name && r.parts.include?(:id) }
                .map { |r| r.defaults[:action] }
                .map(&:to_sym)
        end
    
    end
    
    class UsersController < ApplicationController
        before_action set_model, only: member_routes
    end
    

    【讨论】:

    • 您可以在您的 routes.rb 上定义额外的成员操作,对吗?所以,我也想包括这些。
    • 是的,正如我所说,您只有 2 个选择,将您的 my_member_action 操作添加到列表中,或者使用 :except,就是这样。
    • 重点是使用一些 Rails 魔法来获取所有成员路线并为我生成列表:-)
    • 我更新了我的答案,它没有经过测试,除了在控制台中,但这有点像你想要的(= 返回可以在 all_member_routes 方法中使用的成员操作名称数组)。我真的不认为你应该这样做,但这取决于你;)
    • 你能解释一下为什么我不应该这样做吗?如果是成员动作,是不是自然要让那个成员做动作呢?有什么缺点?
    【解决方案2】:

    如果您要求before_action 不带:only:except 选项,它将适用于所有成员操作:

    class ApplicationController < ActionController::Base
      before_action :require_login
    
      private
    
      def require_login
        unless logged_in?
          flash[:error] = "You must be logged in to access this section"
          redirect_to new_login_url # halts request cycle
        end
      end
    end
    

    在这种特殊情况下,它需要从所有控制器上的所有操作登录,因为控制器将继承自 ApplicationController。

    如果需要,您可以跳过before_action(例如,如果您想将require_login 跳过到系统中,则需要跳过loginsign up),如下所示:

    class LoginsController < ApplicationController
      skip_before_action :require_login, only: [:new, :create]
    end
    

    来源:Rails Guides


    因此,在您的特定情况下:

    你可以有一个普通的用户控制器:

    class UserController < ApplicationController
      def index
      end
    
    
      ...
      /* you define here `index`, `create`, `update`, ... */
      def destroy
        ...
      end
    end
    

    您可以拥有一个包含所有成员操作的单独控制器:

    class UserCustomController < ApplicationController
      before_action :set_model
    
      def profile
        ...
      end
    
      def preview
      end   
    
      def custom_member_action
      end
    
      ...
      /* all your member actions */
    end
    

    这实际上比拥有一个包含许多方法的控制器要好。

    【讨论】:

    • 我的问题的想法是在我的 routes.rb 上添加一个新的成员路由,并且不需要在任何数组上添加任何内容,不管是 only 还是 except 数组。
    • 你的意思是resources :user 例如为用户模型生成路由?
    • like resources :user do member do get :profile done done - 这是一个自定义成员路由。更多信息rails guide
    • fotanus,我不确定这是否是您要找的东西,但是因为您应该尝试坚持 Rails 中控制器的 REST 操作,并且在同一个控制器中没有很多操作...这可以满足您的需求。
    • 感谢您的回答。这可以工作,除了我更喜欢手动列出控制器。请注意,在同一个控制器上添加新的 RESTful 操作并不是什么坏事,软件也不会因为添加更多操作而停止 RESTful。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 1970-01-01
    • 2013-07-20
    相关资源
    最近更新 更多