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.

There was a problem

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