使用Rails 4时,我注意到它定义了before_action
过滤器set_[model]
,该行为show
,edit
,update
和destroy
。
它实际上非常有用,但我没有意识到没有将它用于所有成员行动。毕竟,如果您正在使用成员操作,那么您希望对该成员执行操作,因此您需要在某个时刻从数据库中恢复它。
请注意,通过成员操作,我还表示routes.rb
块中members
上配置的操作。
是否有直接的方法来执行此操作,而无需列出before_action
过滤器上的所有成员操作?
编辑:为了澄清,重点是使用一些rails magic获取所有成员路由并生成将在:only
中传递的数组。所以我可以做类似
before_action set_model only: all_member_routes
其中all_member_routes
是一段代码,它返回我模型的所有成员路由。
甚至更好,
before_action set_model, only_member_actions: true
答案 0 :(得分:6)
show
,edit
,update
,destroy
操作正是所有成员操作。他们是唯一需要找到模型的人。
如果您有自己的成员操作,那么您必须自己将其添加到列表中。
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]
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
答案 1 :(得分:3)
如果您要求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
进入系统或login
,则需要跳过sign up
) :
class LoginsController < ApplicationController
skip_before_action :require_login, only: [:new, :create]
end
来源:Rails Guides
所以,在你的特定情况下:
你可以有一个常用的UserController:
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
这实际上比拥有大量方法的单个控制器更好。