Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Dirty checking is broken for string join

#608

Rails 2.1:

create_table :topics do |t|

t.string :title

end

class Topic < ActiveRecord::Base

end

in console:

>> t = Topic.find(1)

>> t.title = t.title << "new"

>> t.changed?

=> false

Reported by quake wang · July 13th, 2008 @ 04:14 AM

State: invalid
Milestone: 2.x
Assigned to: nobody
Importance: none

Activity

  1. Jason Dew
    Jason Dew

    Don't see an easy fix, but a workaround is s/<</+=/

    July 14th, 2008 @ 05:30 PM

  2. Jason Dew
  3. Tom Ward
    Tom Ward

    This ticket is invalid. Dirty checking will only currently work if you replace an attribute with a new value, not edit it in place.

    Instead you should do:

    t = Topic.find(1)
    t.title_will_change!
    t.title = t.title << "new"
    t.changed?
    # => true
    

    July 25th, 2008 @ 12:26 PM

  4. Clemens Kofler
    Clemens Kofler
    • Tag set to activerecord

    I agree with Tom. It is known that all changes that don't go through standard assignment with = will not mark the attribute as changed.

    July 25th, 2008 @ 02:22 PM

  5. quake wang
    quake wang

    I know will_change can resolve this issue as a temp solution, however, how to explain the inconsistent of string / numeric field?

    create_table :topics do |t|

    t.string :title

    t.integer :score

    end

    t = Topic.find(1)

    t.title = t.title.contact(33)

    t.changed?

    1. => false

    t.score = t.score.*(33)

    t.changed?

    1. => true

    July 26th, 2008 @ 02:26 AM

  6. Tom Ward
    Tom Ward

    What does t.title.contact(33) do?

    If you set the title to the same value it was before, changed? will return false.

    If you set it to a new value, it should return true.

    July 26th, 2008 @ 10:30 AM

  7. Pratik
    Pratik
    • State changed from new to invalid

    Patch please.

    July 26th, 2008 @ 03:19 PM

  8. Clemens Kofler
    Clemens Kofler

    I've tested this and I can confirm it.

    A little something to think about before someone actually spends time on creating a patch that isn't really necessary:

    With t.title << "new", I would actually think that the title changes. t.title = t.title << "new" looks intriguing to me because it looks like it does the actual assignment twice. IMO you shouldn't "reassign" the variable when using the << operator.

    What would make sense, though, is having something like t.title = t.title + "new" or its short form, t.title += "new". Both of them actually work perfectly fine and t.title_changed? returns true.

    The important question to ask is whether one should use something misleading like t.title = t.title << "new" when there's two valid ways around that even look more logical. One is, as I said, t.title += "new" and the other would be to use t.title_will_change! t.title << "new".

    July 26th, 2008 @ 03:29 PM

  9. Zach Holman
    Zach Holman

    I can confirm this as well.

    There's some discussion on whether something is "changed" if the contents are changed. To me that seems like a valid case. I was working on a serialized array to a model, and if I do something like:

    @

    my_model.serialized_array << 'new pushed element'

    my_model.changed # intuitively this should return ["serialized_array"]

    @

    I feel that this is a common scenario where a serialized array needs modification, and the very idea of something being modified is, well, a change.

    July 31st, 2008 @ 09:00 PM