Reloading attributes on out-of-date instances

63 views
Skip to first unread message

Phil Stewart

unread,
May 10, 2011, 1:24:47 PM5/10/11
to Ohm Ruby
Hi all,

Sometimes instances of objects become out of date compared to the
version stored in redis. For example, consider the scenario where two
different instances are manipulating the same object:

class MyModel < Ohm::model
attribute :attr_1
end

first_instance = MyModel.new(:id => 1)
first_instance.attr_1 = "original value"
first_instance.save
first_instance.attr_1
=> "original value"

second_instance = MyModel.new(:id => 1)
second_instance.attr_1 = "new value"
second_instance.save
second_instance.attr_1
=> "new value"

first_instance.attr_1
=> "original value"

This behaviour seems to stem from Ohm::Model's lazy loading of
attributes in to @_attributes: once loaded on first access, they are
not actively reloaded at any point (as far as I can tell). One way
round this is to define a reload attributes method:

class MyModel < Ohm::Model
def reload_attributes
@_attributes.clear
end
end

first_instance.reload_attributes
first_instance.attr_1
=> "new value"

This works by clearing all attributes cached in the @_attributes hash,
thus forcing a lookup to the db for the next time each attribute is
accessed. However, any unsaved changes are lost.

Is this a sensible approach to reloading/synchronisation? Thoughts?

--
Phil Stewart

Damian Janowski

unread,
May 24, 2011, 10:49:55 PM5/24/11
to ohm-...@googlegroups.com
On Tue, May 10, 2011 at 2:24 PM, Phil Stewart <phil.s...@gmail.com> wrote:
> Hi all,
>
> Sometimes instances of objects become out of date compared to the
> version stored in redis. For example, consider the scenario where two
> different instances are manipulating the same object:
>
> class MyModel < Ohm::model
>  attribute :attr_1
> end
>
> first_instance = MyModel.new(:id => 1)
> first_instance.attr_1 = "original value"
> first_instance.save
> first_instance.attr_1
> => "original value"
>
> second_instance = MyModel.new(:id => 1)
> second_instance.attr_1 = "new value"
> second_instance.save
> second_instance.attr_1
> => "new value"
>
> first_instance.attr_1
> => "original value"

In what case would you need the first instance to reflect the new
values set by the last one?

While this looks 'weird', in practice it's not a big deal for most
applications. However, the actual problem is on save. You could save
from first_instance without any warning. I think we should provide an
optimistic locking mechanism based on a timestamp of last
modification. https://github.com/soveran/ohm/issues/29

> This behaviour seems to stem from Ohm::Model's lazy loading of
> attributes in to @_attributes: once loaded on first access, they are
> not actively reloaded at any point (as far as I can tell). One way
> round this is to define a reload attributes method:
>
> class MyModel < Ohm::Model
>  def reload_attributes
>    @_attributes.clear
>  end
> end
>
> first_instance.reload_attributes
> first_instance.attr_1
> => "new value"
>
> This works by clearing all attributes cached in the @_attributes hash,
> thus forcing a lookup to the db for the next time each attribute is
> accessed. However, any unsaved changes are lost.

Right, reloading is not ideal and in any case you still have the same
problem with high contention. BTW, instead of implementing the reload
method, you could simply do MyModel[first_instance.id].

Reply all
Reply to author
Forward
0 new messages