假设我的控制器看起来像这样:
class MyController < ApplicationController
before_filter :find_user,:only => [:index,:create,:update,:destroy]
def index
@some_objects = @user.objects.all
end
...
private
def find_user
@user = User.find(params[:user_id])
end
end
如果user_id
param不存在,@ user将为nil。我认为这不是这样的:
def index
if @user
@some_objects = @user.objects.all
else
# ?
end
end
在我的控制器中进行所有这些检查代码看起来更加丑陋...更不用说如果其他控制器与此类似,我必须复制很多逻辑。 你如何处理这些案件?
答案 0 :(得分:2)
如果user_id
参数不存在,则find
方法抛出ActiveRecord::RecordNotFound
异常。此异常捕获在before_filter和呈现的错误中。 Аll后续过滤器和index
操作将不会被调用。
class MyController < ApplicationController
before_filter :find_user,:only => [:index,:create,:update,:destroy]
def index
@some_objects = @user.objects.all
end
private
def find_user
@user = User.find(params[:user_id])
rescue ActiveRecord::RecordNotFound
# render or redirect_to error
end
end
答案 1 :(得分:1)
我认为它应该放在同一个过滤器中:
private
def find_user
@user = User.find_by_id(params[:user_id])
redirect_to where_you_want_to_go_when_no_user_url unless @user #for example login page
end
如果你想在没有@user的情况下呈现你的控制器动作而你总是需要@some_objects(并且你不希望变量为null),你可以有另一个before_filter:
def get_some_objects
@some_objects = @user.present? ? @user.objects.all : []
end
或组合两个选项(重定向或设置some_objects变量):
def set_variables
@user = User.find_by_id(params[:user_id])
if @user
@some_objects = @user.objects.all
else
redirect_to where_you_want_to_go_when_no_user_url
end
end
我希望这会有所帮助。
编辑:当id为null或者给定id的用户不存在时,将'find'更改为'find_by_id'以避免错误。
答案 2 :(得分:1)
答案 3 :(得分:0)
当您要求特定ID并且AR无法找到它时,它会抛出RecordNotFound错误。 你必须抓住这样的东西:
irb(main):025:0> begin
irb(main):026:1* Location.find 100
irb(main):027:1> rescue ActiveRecord::RecordNotFound => e
irb(main):028:1> puts "Oops: #{e.message}"
irb(main):029:1> end
Oops: Couldn't find Location with ID=100
=> nil
如果您想对所有控制器应用某些内容,您应该考虑将您的方法添加到ApplicationController ......