
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
end
So in my controller when I update it I call the following
if @document.update_attributes(params[:document]) || !(@document.dirty?)
redirect url(:document, @document)
else
render :edit
end
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)
end
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 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 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.