2

In my rails model, I have a decimal property called employer_wcb. I would like it if, when employer_wcb was changed, a dirty bit was set to true. I'd like to override the employer_wcb setter method. Any way to do so (in particular using metaprogramming)?

Steve Graham
  • 3,001
  • 1
  • 22
  • 26
Daniel
  • 16,026
  • 18
  • 65
  • 89

2 Answers2

8

So actually, as of Rails v2.1, this has been baked into Rails. Have a look at the documentation for ActiveRecord::Dirty. In summary:

# Create a new Thing model instance;
# Dirty bit should be unset...
t = Thing.new
t.changed?              # => false
t.employer_wcb_changed? # => false

# Now set the attribute and note the dirty bits.
t.employer_wcb = 0.525
t.changed?              # => true
t.employer_wcb_changed? # => true
t.id_changed?           # => false

# The dirty bit goes away when you save changes.
t.save
t.changed?              # => false
t.employer_wcb_changed? # => false
Andres Jaan Tack
  • 22,566
  • 11
  • 59
  • 78
  • Absolutely. Two caveats though: We don't know which version of Rails is being targeted (unlikely to be an issue but hey!) and I do not believe that ActiveRecord::Dirty tracks virtual attributes. Asker did not specify nature of employer_wcb. – Steve Graham Dec 15 '09 at 01:44
  • +1 - @Daniel: This is the best answer to accept if you're using > 2.1 and employer_wcb is not a virtual attribute. – Steve Graham Dec 15 '09 at 02:13
  • ActiveRecord::Dirty was a plugin before accepted into 2.1. http://code.bitsweat.net/svn/dirty/ – EmFi Dec 15 '09 at 03:32
2

If you don't want to use rail's built in dirty bit functionality (say you want to override for other reasons) you cannot use alias method (see my comments on Steve's entry above). You can however use calls to super to make it work.

  def employer_wcb=(val)
    # Set the dirty bit to true
    dirty = true
    super val
  end

This works just fine.

Daniel
  • 16,026
  • 18
  • 65
  • 89