我正在研究一个RoR项目,我正在尝试更新列的日期时间。我创建的列名为“deleted_at”,控制器中的代码是下一个:
def destroy
p DateTime.now
p Time.now.to_formatted_s(:db)
domain = Domain.find(params[:id])
p "RECORD: " + domain.domain.to_s
domain.update(deleted_at: Time.now.to_formatted_s(:db))
respond_to do |format|
format.html { redirect_to @domain, notice: 'Domain was successfully deleted' }
format.js { render action: "destroy" }
end
end
如果我尝试更新另一个不同的列,例如域名,我可以做到没有任何问题。否则,无法更新deleted_at列。我尝试过许多不同的方式,但我什么都没得到。
这是执行destroy方法时来自Rails控制台的日志:
Started DELETE "/domains/28" for 10.0.2.2 at 2013-09-06 12:56:35 +0000
Processing by DomainsController#destroy as JS
Parameters: {"id"=>"28"}
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 13 ORDER BY `users`.`id` ASC LIMIT 1
Fri, 06 Sep 2013 12:56:36 +0000
"2013-09-06 12:56:36"
Domain Load (0.3ms) SELECT `domains`.* FROM `domains` WHERE `domains`.`id` = 28 LIMIT 1
"RECORD: www.example.com"
(0.3ms) BEGIN
Domain Load (0.6ms) SELECT `domains`.* FROM `domains` WHERE `domains`.`domain` = 'www.example.com' AND `domains`.`user_id` = 13 LIMIT 1
(0.4ms) ROLLBACK
Rendered domains/destroy.js.erb (0.1ms)
Completed 200 OK in 104ms (Views: 90.0ms | ActiveRecord: 2.0ms)
正如您所看到的,日期时间格式是正确的并且已正确打印,但更新方法实际上是在执行SELECT而不是UPDATE。
我的朋友出了什么问题?
感谢。
编辑 -------------------
感谢大家,我发现了问题(虽然还没有解决方案)。这是一个验证规则。我打印了错误,我得到了:
ERROR: You already have this domain in use.
此消息由(domain.rb)引发:
class Domain < ActiveRecord::Base
validate :domainIsUnique?
private
def domainIsUnique?
if Domain.find_by domain: domain, user_id: user_id
# Domain and user_id found, throwing error
errors.add(:domain, "You already have this domain in use.")
end
end
end
因此,我无法更新任何内容,因为此验证总是搞砸了这个过程。我不明白的是,如果我只是更新,而不是添加......
,为什么这个验证会自行提升答案 0 :(得分:2)
为什么要使用自定义验证?您应该能够确定唯一性验证的范围
class Domain < ActiveRecord::Base
validates :domain, presence: true, uniqueness: {scope: :user_id}
end
应该做与自定义相同的事情。并且应该在更新上正常工作。
因为这个版本会忽略它自己更新的记录,而你自己没有这样做,因此你得到验证失败的原因。
答案 1 :(得分:1)
我认为Doon是在正确的轨道上......当你尝试更新任何东西时,你的验证将会失败,因为它只是在搜索某个特定域和用户的记录,在更新时总会有这样的记录,因为记录你正在更新自己满足你的条件......
您可以接受Doon的解决方案,即向用户添加作用域的唯一性验证,或者仅在create上运行验证。 e.g。
validate :domain_is_unique?, on: :create
糟糕,只是在您更新域名时看到了有关它的编辑工作...由于您的验证是在检查用户和域,因此您可能希望这样做。如果您更改其中任何一个,那么您的“脏”记录将不再与您的验证查询匹配。
所以要明确的是,您可以更新用户或域,但任何其他更新都会导致验证失败,因为查询与域和用户上的当前对象匹配。
答案 2 :(得分:0)
修改强>
这应该有效
domain.update(deleted_at: Time.now.utc)
尝试拆分为手动设置然后保存。无论结果是否保存到数据库,Update都将返回该类。
domain.deleted_at = Time.now
raise "Error saving!" unless domain.save
请参阅docs。
如果验证通过,则更新对象(或多个对象)并将其保存到数据库。无论对象是否已成功保存到数据库,都会返回结果对象。
答案 3 :(得分:0)
请尝试使用以下内容更新列。
def destroy
domain = Domain.find(params[:id])
domain.update_attributes(deleted_at: Time.now.utc) # or Time.now
respond_to do |format|
format.html { redirect_to @domain, notice: 'Domain was successfully deleted' }
format.js { render action: "destroy" }
end
end