0

That ActiveModel::Dirty doesn't cover Array.push (or any other modify-in-place methods, as I've read extremely recently) for attributes pertaining to, say, postgres arrays is pretty well-established. For example, if an Apple model has an array Apple.seeds, you'll see the following in a Rails console.

johnny = Apple.new()
# => <Apple #blahblahblah>
johnny.seeds
# => [] (assuming [] default)
johnny.seeds << "Oblong"
# => ["Oblong"]
johnny.changed?
# => false
johnny.seeds = []
johnny.seeds += ["Oblong"]
# => ["Oblong"]
johnny.changed?
# => true

So you can use two different ways of changing the array attribute, but Rails only recognizes the one that uses a setter. My question is, is there a way (that won't mangle the Array class) to get push to behave like a setter in the context of an ActiveRecord object, so that johnny.seeds << (x) will reflect in johnny.changes?

(On my end, this is to prevent future developers from using push on array attributes, unwittingly failing to record changes because they were not aware of this limitation.)

Community
  • 1
  • 1
Vardarac
  • 563
  • 2
  • 17

1 Answers1

1

This is a problem with any column with a mutable object, not just Array objects.

seeder = Apple.first
seeder.name
=> "Johnny "

seeder.name << " Appleseed"
seeder.changed?
=> false

You're better off leaving a note for future developers, but otherwise you can consider replacing the changed? method

class Apple

  alias_method 'old_changed?', 'changed?'

  def changed?
    return old_changed? if old_changed?
    return (seeds.count > 0) if new_record?
    return seeds != Apple.find(id).seeds
  end

end

However, note that just because changed? comes backtrue, does not assure you that fields with unchanged object_ids will be updated in update_attributes... you may find that they're not. You might need to hire competent rails developers who understand these pitfalls.

SteveTurczyn
  • 36,057
  • 6
  • 41
  • 53