and*_*lho 32 validation ruby-on-rails ruby-on-rails-4
我有一个案件正在绕过我的脑袋.
我有一个Image模型,如果上传的话我只想保存.我还需要一些来自上传的信息来验证图像(如高度和宽度).但是我想只有在第一次尝试将文件保存到文件时才会发生上传.
所以我认为最好的选择是拥有一个before_validation
,但我希望它只能在保存时运行!
我的代码在这个要点上https://gist.github.com/andreorvalho/b21204977d2b70fdef83
所以奇怪的部分是这个,on: :save
并且on: :create
有非常奇怪的行为,或者至少不是我的预期.
当我把它作为on: :save
我试图做image.save
一个测试我可以看到我的before_validation
回调没有运行!
如果我on: :create
在每种情况下运行都没关系,如果我跑了image.save
,image.create
或者image.valid?
所以我猜这不是工作,或者我误解了设置的目标.
ps我的创建验证,也发生在每种情况下保存,创建或有效?
让我知道是否有人碰到相同或知道为什么不应该像这样工作.
Jon*_*Jon 65
自从最初编写此答案以来,before_validation
回调已更新为允许限制对象生命周期内的特定事件.您现在可以使用以下语法:
before_validation :set_uuid, on: :create
before_validation :upload_to_system, on: [:create, :update]
Run Code Online (Sandbox Code Playgroud)
该before_validation
回调将验证之前被执行.每次.你不能限制它before_validation
或before_validation
我特别害怕的行动.
你应该做这样的事情:
before_validation :set_uuid, on: :create
before_validation :upload_to_system, on: [:create, :update]
Run Code Online (Sandbox Code Playgroud)
before_validation
您传递的选项将在您的验证中使用,就像您在before_validation
验证时所做的那样.
我遇到了同样的问题,这就是我发现的。
#valid?
是一种方法,它还接受一个名为的可选参数context
(由于某种原因很多人都不知道,包括我在偶然发现这个问题并做了一些研究之前)。调用context
该#valid?
方法时传入 将会导致仅before_validation
运行那些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
Run Code Online (Sandbox Code Playgroud)
现在,打电话:
Model.new.valid?(:create)
Run Code Online (Sandbox Code Playgroud)
只会运行:some_method
。同样调用:
Model.new.valid?(:update)
Model.new.valid?(:save)
Model.new.valid?(:custom)
Run Code Online (Sandbox Code Playgroud)
只会分别运行:another_method
、:yet_another_method
、 和:also_another_method
。但是,如果我们这样做:
Model.new.valid?(:unknown)
Run Code Online (Sandbox Code Playgroud)
那么它不会调用任何回调,因为我们:unknown
在创建回调时没有指定为上下文。
context
另外,另一件事需要注意的是,如果我们在调用时不传递 a #valid?
,那么 ActiveRecord 将在内部使用该new_record?
方法来计算它。也就是说,如果new_record?
返回true
,则context
会被设置为:create
,但如果返回false
,则context
会被设置为:update
。
当我将其设置为“
on: :save
如果我尝试进行image.save
测试”时,我可以看到我的before_validation
回调没有运行!
这是因为 ActiveRecord 的#save
方法在内部调用时#valid?
不传递显式context
,这意味着现在该#valid?
方法必须根据 . 返回的布尔值来决定是否使用:create
or:update
作为 a 。由于您已指定,因此它不会运行。是的,没错,ActiveRecord 内部不存在上下文。context
#new_record?
on: :save
:save
如果我
on: :create
在每种情况下都跑了,那么我跑了并不重要image.save
,image.create
或者image.valid?
这是事实,但前提是这image
是一个新记录。尝试对现有记录执行相同的操作,它不会运行。