我试图使用Rails实现Repository模式的一个子集,并且在理解如何从类或存储库传递错误,返回控制器然后进入视图时遇到一些麻烦。
例如,我有一个类DomainClass
,它只允许用户注册一个子域。那里有一些规则 - 它必须是唯一的,必须只包含字母和数字 - 你有什么。
当一个或多个模型验证失败时,我想以某种方式将此值传递给视图。在传递这些错误的同时,我还必须返回" false"对控制器来说,它知道无论我试图做什么都失败了。
这看起来很简单。我在这里缺少什么?
Class - if this fails, I should pass the validation error to my controller.
# Create a domain ID and return the newly injected ID.do
# If a new Domain ID couldn't be created for any reason,
# return FALSE.
def create_domain(domain_name)
@domain.domain_name = domain_name
if @domain.save
return @domain.id
else
return false
end
end
Controller - From here, I should return the model's validation error to the view.
# Try to save our user to the database
if new_user = @domain.create_domain(domain_name)
# Do things that are good.
else
# Return model's validation error here.
end
答案 0 :(得分:1)
我看到了两种设计create_domain
的选项,当你在一些非ActiveRecord商店上重新实现它时仍然有意义。您将使用哪一个取决于您期望使用它的情况。
定义一个类来保存所有create_domain
可能的返回值。这将是一个开始:
class SaveResult < Struct.new :id, :errors
def succeeded?
errors.empty?
end
end
在create_domain
,
return SaveResult.new *(
if @domain.save
@domain.id, []
else
nil, @domain.errors # this is an ActiveModel::Errors, but tell your callers it's a Hash
end
)
然后调用者可以执行类似
的操作result = @domain.create_domain name
if result.succeeded?
# celebrate
else
# propagate errors to model
end
这种设计的缺点是呼叫者必须记住检查是否有错误。如果大多数调用者必须明确地处理错误(如上所述),那么它将很有效。
定义出现错误时引发的异常:
class SaveError < Exception
attr_accessor :errors # again, pretend it's just a hash
def initialize(errors)
self.errors = errors
end
end
在create_domain
,
if @domain.save
return @domain.id
else
raise SaveResult, @domain.errors
emd
然后调用者可以执行类似
的操作begin
new_user_id = @domain.create_domain name
# celebrate
rescue SaveError => e
# propagate errors to model
end
这种设计的缺点是异常处理比if
/ else
更难写。它的优点是,如果你只是允许所有这些异常传播出调用者并在ActionController#rescue_from
或类似的地方处理它们,那么调用者根本不需要编写任何错误处理。 / p>