1

我正在做一个 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

正因为如此,我无法更新任何东西,因为这个验证总是搞砸了这个过程。我不明白的是,如果我只是更新而不是添加......

4

4 回答 4

2

为什么要使用自定义验证?您应该能够确定唯一性验证的范围

class Domain < ActiveRecord::Base
    validates :domain, presence: true, uniqueness: {scope: :user_id}
end

应该做与您的自定义相同的事情。并且应该在更新上也能正常工作。

http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_uniqueness_of

因为这个版本会忽略它自己的更新记录,而你的版本不会这样做,因此你的验证失败了。

于 2013-09-06T23:42:06.883 回答
1

我认为 Doon 走在正确的轨道上......只要您尝试更新任何内容,您的验证就会失败,因为它只是在搜索是否存在特定域和用户的记录,更新时总是存在,因为您的记录是更新本身满足您的条件...

您可以接受 Doon 为用户添加唯一性验证的解决方案,或者只在创建时运行验证。例如

validate :domain_is_unique?, on: :create

哎呀,如果您更新域,刚刚看到您对其进行的编辑......您希望它可以工作,因为您的验证正在检查用户和域。如果您更改其中任何一个,那么您的“脏”记录将不再与您的验证查询匹配。

所以要清楚,您将能够更新用户或域,但任何其他更新都会导致验证失败,因为查询匹配域和用户上的当前对象。

于 2013-09-07T15:05:09.290 回答
0

编辑

这应该工作

domain.update(deleted_at: Time.now.utc)

尝试拆分为手动设置,然后保存。无论结果是否保存到数据库,更新都会返回该类。

domain.deleted_at = Time.now
raise "Error saving!" unless domain.save

请参阅文档

如果验证通过,则更新一个对象(或多个对象)并将其保存到数据库中。无论对象是否成功保存到数据库,都会返回结果对象。

于 2013-09-06T13:07:07.667 回答
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
于 2013-09-06T13:53:45.673 回答