#461 ✓resolved
Jorge Calás

update_attributes wrong behaviour with lazy attributes

Reported by Jorge Calás | July 16th, 2008 @ 02:36 PM

Having a model with lazy attributes (Text in my case) I got unexpected results when I call update_attributes with unchanged values. For example:

class Document
  include DataMapper::Resource

  property :id, Integer, :serial => true
  property :title, String
  property :description, Text

So in my controller when I update it I call the following

if @document.update_attributes(params[:document]) || !(@document.dirty?)
  redirect url(:document, @document)
  render :edit

The problem is when the new value is the same as the current of the lazy loaded attribute, because it marks it dirty, when it's actually not.

I've investigated a little bit, and the problem is when it is trying to set the new value it doesn't have the current value so the comparison is false.

# dm-core/lib/property.rb:414

    def set(resource, value)
      new_value = typecast(value)
      old_value = get!(resource)

      # skip setting the property if the new value is equal
      # to the old value, and the old value was defined
      return if new_value == old_value && resource.attribute_loaded?(name)

      resource.original_values[name] = old_value unless resource.original_values.has_key?(name)

      set!(resource, new_value)

As we see here it tries to compare old_value (which is nil because it's not loaded) to the new_value. So it goes and mark it as dirty.

This wouldn't be a problem, we might just overwrite the value, but the mysql adapter is returning false. It says that no row was updated, which would be right since the values are the same.

I think the solution would be to force loading when updating a record, but I don't know if that would be the best path.

Comments and changes to this ticket

  • Bernerd Schaefer

    Bernerd Schaefer July 22nd, 2008 @ 02:46 PM

    • State changed from “new” to “resolved”

    Thanks for pointing this out. As of 450fee3, we lazy-load properties on Property#set as well as Property#get, which should resolve this for you.

  • Marcin Kulik

    Marcin Kulik November 18th, 2008 @ 06:11 AM

    I have the same issue in dm 0.9.7 from git (I've pulled it yesterday). I'm updating project object passing new name (which is String property on model) and description (Text property, lazy loaded) to update_attributes. Passed name is different than old one, description is the same. update_attributes doesn't update the record. I've noticed that when calling update_attributes(params[:project]) twice the second call executes the update. Additionally changing description property to :lazy => false makes update_attributes work as it should.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

People watching this ticket