Ruby on rails Rails服务对象,向新模型添加错误
我最近有一个rails模型,它有几个回调,如下所示:Ruby on rails Rails服务对象,向新模型添加错误,ruby-on-rails,ruby,web-services,ruby-on-rails-4,refactoring,Ruby On Rails,Ruby,Web Services,Ruby On Rails 4,Refactoring,我最近有一个rails模型,它有几个回调,如下所示: class Model < ActiveRecord::Base before_validation :fetch_posts after_create :build_posts def fetch_posts fetch_collection rescue MyException => e self.errors.add(:post, e.message) end def build
class Model < ActiveRecord::Base
before_validation :fetch_posts
after_create :build_posts
def fetch_posts
fetch_collection
rescue MyException => e
self.errors.add(:post, e.message)
end
def build_posts
fetch_collection.each do |item|
DifferentModel.build(item)
end
end
def fetch_collection
@collection ||= method_that_fetches_collection_from_external_source
end
end
我现在看到的问题是,如果一个模型确实包含一个错误(来自fetch posts方法),它不会被带入到SO中的model.save
调用中。也就是说,Model.new
有一个错误,但是一旦我对该模型调用了.save
。new
它不会维护错误,并且模型会正确保存
我考虑过添加validate:fetch_posts
,但后来我又回到了以前的状态,因为这本质上是一个回调
有没有关于如何更好地构建此结构的建议?是否可以维护从Model.new
到.save
的错误?我根本上误解了什么吗
谢谢 这里有一个替代解决方案,即覆盖
运行\u验证代码>因为你没有
class Model < ActiveRecord::Base
after_create :build_posts
def fetch_posts
fetch_collection
rescue MyException => e
self.errors.add(:post, e.message)
end
def build_posts
fetch_collection.each do |item|
DifferentModel.build(item)
end
end
def fetch_collection
@collection ||= method_that_fetches_collection_from_external_source
end
private
def run_validations!
fetch_posts
errors.empty?
end
end
但是,由于您没有验证,它应该在#save
上起到类似的作用
或者,正如我在评论中所建议的,您可以用模型错误替换保存
。任何?
因为保存
将清除由获取帖子设置的原始错误,但是错误。任何?
将检查获取帖子
方法期间是否存在错误。您的验证是什么?不确定我是否完全理解该场景。@engineersmnky本身没有验证,如果我从外部调用中得到错误,我只会抛出一个异常,而:before\u validate回调中的:fetch\u posts方法只会向模型添加一个错误,因此无法保存。这是最接近验证的东西。好的,这里的问题是,您正在使用fetch\u posts
,它将生成错误,但是当您保存它时,它将清除错误并再次运行fetch\u posts
,这一次不会失败,因为它只是简单地调用不会失败的@collection
。当save
在验证之前通过调用它时,为什么在save
之前调用fetch\u posts
?您可以尝试model.fetch_posts
,然后model.errors.any?
而不是save
@engineersmnky,这很有意义。在服务对象示例中,我删除了回调,这样在验证之前就不会运行。但是我会处理model.errors.any?
的问题,看看我是否能让它这样工作。是的,问题是save
没有运行任何验证,所以它总是正确的,所以你需要通过另一种方法检查是否有任何错误。
class Model < ActiveRecord::Base
after_create :build_posts
def fetch_posts
fetch_collection
rescue MyException => e
self.errors.add(:post, e.message)
end
def build_posts
fetch_collection.each do |item|
DifferentModel.build(item)
end
end
def fetch_collection
@collection ||= method_that_fetches_collection_from_external_source
end
private
def run_validations!
fetch_posts
errors.empty?
end
end
def run_validations!
run_callbacks :validate
errors.empty?
end