rails 4 before_validation on :: create或on :: save

时间:2014-01-27 22:23:44

标签: ruby-on-rails validation ruby-on-rails-4

我正在审理一个案件。

我有一个Image模型,如果上传的话我只想保存。我还需要来自上传的一些信息来验证图像(如高度和宽度)。但是我想只有在第一次尝试将文件保存到文件时才会发生上传。

所以我认为最好的选择是拥有before_validation,但我希望它只能在保存时运行!

我的代码就在这个要点https://gist.github.com/andreorvalho/b21204977d2b70fdef83

所以奇怪的部分是这个on: :saveon: :create有非常奇怪的行为,或者至少不是我的预期。

当我将其设为on: :save如果我尝试在测试中执行image.save,我可以看到我的before_validation回调没有运行!

如果我在on: :createimage.saveimage.create

运行image.valid?,{{1}}

所以我猜这可能不起作用,或者我误解了设置目标。

P.S。我对创建的验证,也发生在保存,创建或有效的每种情况下?

让我知道是否有人遇到同样的人或者知道为什么不应该像这样工作。

2 个答案:

答案 0 :(得分:59)

更新

由于最初编写此答案,before_validation回调已更新,以允许限制对象生命周期内的特定事件。您现在可以使用以下语法:

before_validation :set_uuid, on: :create
before_validation :upload_to_system, on: [:create, :update]

旧答案

before_validation回调将在验证前执行。每次。您不能将此限制为savecreate具体我害怕的行为。

你应该做这样的事情:

before_create :set_uuid
after_save :upload_to_system

您传递的on: :create选项可以在您的验证中使用,就像您使用:source_file_path验证一样。

答案 1 :(得分:0)

我遇到了同样的问题,这就是我发现的问题。

lapply( variables , function( z ) svyby( as.formula( paste0( "~" , z ) ) , by = ~gender + age + location, design = srs_design, FUN = svytotal, na.rm = TRUE, row.names = FALSE)) 是一种方法,它也接受称为#valid?的可选参数(由于某些原因,包括我在内,很多人都不知道,因为我偶然发现了这个问题并进行了一些研究)。在调用context方法时传递context只会导致运行使用#valid?键设置了相同before_validation的{​​{1}}回调

示例

假设我们有以下代码:

context

现在,打电话:

:on

将仅运行class Model < ActiveRecord::Base before_validation :some_method, on: :create before_validation :another_method, on: :update before_validation :yet_another_method, on: :save before_validation :also_another_method, on: :custom end 。同样调用:

Model.new.valid?(:create)

将分别仅运行:some_methodModel.new.valid?(:update) Model.new.valid?(:save) Model.new.valid?(:custom) :another_method。但是,如果这样做:

:yet_another_method

然后它将不会调用任何回调,因为我们在创建回调时未指定:also_another_method作为上下文。

还要注意的另一件事是,如果我们在调用Model.new.valid?(:unknown) 时没有传递:unknown,则ActiveRecord将在内部使用context方法来解决它。也就是说,如果#valid?返回new_record?,则new_record?将设置为true,但是如果返回context,则:create将设置为false

回到您的问题

当我将其设置为context时,如果我尝试在测试中进行:update,我可以看到我的on: :save回调没有运行!

这是因为ActiveRecord的image.save方法在内部调用before_validation而不传递显式的#save,这意味着现在#valid?方法将必须决定是否使用{{1} }或context作为#valid?作为:create返回的布尔值。并且由于您指定了:update,所以它不会运行。是的,没错,context上下文在ActiveRecord内部不存在。

如果我把#new_record?都在每种情况下都运行了,则不管我是否运行on: :save:saveon: :create

这是正确的,但前提是image.save是新记录。尝试对现有记录执行相同操作,它将不会运行。