【问题标题】:How to disable tracking of changed attributes in model in active_record如何在 active_record 中禁用跟踪模型中更改的属性
【发布时间】:2015-11-11 17:44:28
【问题描述】:

我有一个简单的模型,它有 3 个属性 idpaylod(二进制数据,大)、created_at

我需要从负载数据中提取一堆值,以便在after_initialize 回调方法中进行进一步处理。由于有效负载可能非常大(~20MB),我想在提取必要信息后通过设置@payload = nil 来处理这些数据,以防止加载一堆条目时出现内存不足的情况。 注意:模型只从数据库中读取,不需要持久化任何更改。

class Payload < ActiveRecord::Base
  after_initialize do |data|
    # extract required values from binary data
    # ... 

    # dispose big data 
    error.payload = nil
    # at this point error.changed_attributes['payload'] 
    # contains the previous payload data (~20MB)
  end
end

如何防止模型在 @changed_attributes 哈希中保留以前的值?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 activerecord rails-activerecord jrubyonrails


    【解决方案1】:

    如果属性设置器方法被重载没有调用super(),所有回调都被禁用并且不跟踪任何更改。

    def payload= ( new_payload )
      @payload = new_payload
    end
    

    在这个带有只读模型的用例中,这可以正常工作。请注意,该模型也没有标记为脏,并且可能会出现其他副作用

    【讨论】:

    • 您是否还需要将新值存储在@new_payload 中?这也可以吗:def payload=(new_payload); end
    • 我喜欢这个主意!在这种特殊情况下,它应该可以工作,假设只想将@payload 设置为nil 以清除它。但是上面的示例通过提供适当的实现来提供更大的灵活性,您可以在其中为其分配任何值。
    【解决方案2】:

    在将 payload 设置为 nil 后调用 clear_changes_information。当然,这仅在您不希望保留其他更改时才有效。

    更新

    例子:

    > user.name
    => "Dave Smith"
    > user.name = nil
    => nil
    > user.changes
    => {"name"=>["Dave Smith", nil]}
    > user.clear_changes_information
    => {}
    > user.changes
    => {}
    

    还有这个方法restore_attributes

    注意,我使用的是 ActiveRecord 4.2.4。

    【讨论】:

    • 我在ActiveModel::Dirty 文档中看到了clear_changes_information 方法,但它在我的对象上不可用。我还在我的模型中尝试了include ActiveModel::Dirty,但没有任何成功。我究竟做错了什么?你能举个例子吗?
    • 该示例提供了我想要的,但对我不起作用。我在after_initialize 块中的error.payload = nil; error.clear_changes_information; 之后收到undefined method clear_changes_information'`。这是使用 jruby-9.0.1.9 和 ActiveRecord 4.1.8。
    【解决方案3】:

    您对不同的方法有何看法?我的意思是你调用一个Active Job 工作人员,它通过调用Service Object 来执行一些工作。最后一个将对您的数据进行操作。提取一些字段,然后将其保存在数据库中。我认为它可以节省大量内存。

    【讨论】:

    • 好主意和在不同场景中的可能方式。这里是关于分析来自外部数据库的数据。提取的值只是临时使用,因此不需要持久化。使用 Active Job 进行后台处理似乎不是正确的方法,因为它意味着直接交互。否则,用户进程将不得不更改为两步操作:1) 分析和 2) 查看/进程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 2023-03-09
    • 2020-07-31
    • 1970-01-01
    相关资源
    最近更新 更多