面试题答案
一键面试1. 过滤器的作用
在Ruby on Rails控制器中,过滤器用于在控制器的动作(action)执行之前、之后或周围运行一段代码。它们提供了一种方便的方式来将通用逻辑集中处理,而不是在每个动作方法中重复编写相同的代码。这有助于保持代码的DRY(Don't Repeat Yourself)原则,提高代码的可维护性和可读性。
2. 不同类型过滤器的特点
- before_action:在控制器的动作方法执行之前运行。可以用于多种目的,例如验证用户权限、设置共享实例变量等。如果某个
before_action
失败(例如返回false
或重定向),则后续的动作方法将不会执行。 - after_action:在控制器的动作方法执行之后运行。通常用于记录日志、发送通知等操作。无论动作方法执行成功与否(即使抛出异常),
after_action
都会运行(除非在异常处理过程中提前终止了请求)。 - around_action:围绕控制器的动作方法运行。它提供了更大的灵活性,可以在动作方法执行前后都运行代码,并且可以控制动作方法是否执行。例如,可以用于事务管理,在动作方法执行前开启事务,执行后根据结果提交或回滚事务。
3. 多用户博客系统中的应用示例
- 用户登录状态检查(使用before_action):
假设我们有一个
PostsController
,用于管理博客文章,只有登录用户才能执行创建、更新、删除等操作。
class PostsController < ApplicationController
before_action :authenticate_user!
def index
@posts = Post.all
end
def new
@post = current_user.posts.build
end
def create
@post = current_user.posts.build(post_params)
if @post.save
redirect_to @post, notice: 'Post was successfully created.'
else
render :new
end
end
private
def authenticate_user!
unless user_signed_in?
redirect_to new_user_session_path, alert: 'You need to sign in first.'
end
end
def post_params
params.require(:post).permit(:title, :body)
end
end
在上述代码中,before_action :authenticate_user!
确保在执行new
、create
等动作方法之前,先调用authenticate_user!
方法检查用户是否登录。如果未登录,则重定向到登录页面。
- 日志记录(使用after_action):
为了记录用户对文章的操作,可以使用
after_action
。
class PostsController < ApplicationController
after_action :log_post_action, only: [:create, :update, :destroy]
def create
# 创建文章逻辑
end
def update
# 更新文章逻辑
end
def destroy
# 删除文章逻辑
end
private
def log_post_action
action = case params[:action]
when 'create' then 'created'
when 'update' then 'updated'
when 'destroy' then 'destroyed'
end
logger.info "#{current_user&.email} #{action} a post with id #{params[:id]}"
end
end
这里after_action :log_post_action, only: [:create, :update, :destroy]
表示仅在create
、update
和destroy
动作执行后调用log_post_action
方法记录操作日志。
4. 相较于在每个方法中单独编写逻辑的优势
- 代码复用:将通用逻辑(如用户登录检查、日志记录)提取到过滤器中,避免在每个需要这些逻辑的动作方法中重复编写,减少了代码冗余。
- 易于维护:如果逻辑需要修改(例如更改登录验证的方式或日志记录的格式),只需要在过滤器中修改一处代码,而不需要在多个动作方法中逐一修改,降低了维护成本。
- 清晰的关注点分离:控制器的动作方法专注于业务逻辑(如处理文章的创建、更新等),而过滤器负责处理通用的横切关注点(如验证、日志记录),使代码结构更加清晰,提高了代码的可读性和可理解性。