rails: Dirty attribute changes for virtual attributes broken between Rails 5.0 and 5.2

I encountered this bug with my own gem https://github.com/uberllama/accepts_nested_ids after upgrading from Rails 5.0 to 5.2. At first I thought I was missing one of the many API changes to Dirty, but upon further investigation, this behavior applies to any ActiveRecord model with virtual attributes that you want to track changes for.

Steps to reproduce

Create models like so:

class NotOrder
  include ActiveModel::Dirty

  def number
    @number
  end

  def number=(val)
    attribute_will_change!(:number) unless val == @number
    @number = val
  end
end

class Order < ActiveRecord::Base
  def number
    @number
  end

  def number=(val)
    attribute_will_change!(:number) unless val == @number
    @number = val
  end
end

Expected behavior

changes returns delta of changes on virtual attribute whether AR or AM model.

# Rails 5.0
norder = NotOrder.new
norder.number = 123
norder.changed # => ["number"]
norder.changes # => { "number" => [nil,123] }

order = Order.new
order.number = 123
order.changed # => ["number"]
order.changes # => { "number" => [nil,123] }

Actual behavior

changes returns nil for new value of virtual attribute on AR model.

# Rails 5.2
norder = NotOrder.new
norder.number = 123
norder.changed # => ["number"]
norder.changes # => { "number" => [nil,123] }

order = Order.new
order.number = 123
order.changed # => ["number"]
order.changes # => { "number" => [nil,nil] }

System configuration

Rails version: 5.2

Ruby version: 2.4.1

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 18 (16 by maintainers)

Most upvoted comments

It was something that was supported but it is not anymore.

@rafaelfranca - its been my experience in the past that things that Rails no longer supports is typically moved to a gem, as to ease the pain of upgrading.

In my case, I am trying to get basic association ID tracking to work in the paper_trail gem and it appears Rails dropped any supported mechanism to do that in Rails 5.1. Tracking association ID’s isn’t a fringe use case, IMHO.

It was something that was supported but it is not anymore.

@rafaelfranca Thanks, the dangers of jumping versions… That being said, adding an attribute declaration for the virtual does not resolve the issue.