> --
> You received this message because you are subscribed to the Google Groups
> "Ruby or Rails Oceania" group.
> To post to this group, send email to rails-...@googlegroups.com.
> To unsubscribe from this group, send email to
> rails-oceani...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/rails-oceania?hl=en.
>
You can't... well... you can... but you have to call reload somewhere.
The way this is handled best is using record locking in conjunction with database transactions which provides access to row and table locking.
Then while you are doing the update, check to make sure that the record has not already been updated before performing your action, all within a transaction.
Hope that nudges you in the right direction.
Mikel Lindsaar
http://rubyx.com/
http://lindsaar.net/
--
--
You should still think carefully about what it is you are trying to do.If you just catch the optimistic locking exception, and automatically reload and save, then you are ensuring the second user's change overwrites the first. The second user will never see the first user's change. That's not really optimistic locking at all.
- Update by John Doe at <time>
- Update by Jane Doe at <time>
- etc...
Make those changes viewable by the users, so everyone knows where
changes are coming from.
If you're concerned about generating too many records, save up to,
say, 20 versions maximum.
> --
> You received this message because you are subscribed to the Google Groups
> "Ruby or Rails Oceania" group.
> To post to this group, send email to rails-...@googlegroups.com.
> To unsubscribe from this group, send email to
> rails-oceani...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/rails-oceania?hl=en.
>
On edit submit, I load the last updated time of the object I'm saving.
If it has changed then I know someone has edited the object since.
Could use some ajax to poll for this change and warn the user before
they submit too.
Eaden
--
mark
--
A UNIX signature isn't a return address, it's the ASCII equivalent of a
black velvet clown painting. It's a rectangle of carets surrounding a
quote from a literary giant of weeniedom like Heinlein or Dr. Who.
-- Chris Maeda
> Something akin to a subscriber/publisher design pattern, where I can subscribe to the DB from rails and say, "Notify me when anything to do with this row" has changed.. and then when something does change the DB is the one that communicates back through the db connection signalling to call .reload…
> Like I don't understand why this is not a standard in any ORM implementation… surely it's never a good situation to be dealing with stale objects at any time
Don't take this the wrong way, but you seem to be misunderstanding the lifecycle of a rails request, and the models it loads during a request?
The thing is, you're working in a stateless web world.
Even if there was some way for the DB to notify you're AR instance that
the underlying data has changed, that instance may have been garbage
collected 30 minutes ago when the original HTTP request was completed.
Meanwhile the user has been staring at their web form for 30 minutes and
has only just decided to hit submit.
Given the nature of HTTP, your realistic options are:
* accept occasional data loss when changes are over-ridden
* optimistic locking like that provided by lock_version
* big chunky application layer locks. Create an AR model called Lock,
have your edit action create a lock, and subsequent requests to the
same action are denied until the user submits the form. Messy, but
sometimes required.
-- James Healy <ji...@deefa.com> Fri, 19 Nov 2010 11:18:50 +1100
Hello,What I really wanted I now believe has to be done and provided by the native DB or implemented via some plumbing connection between rails and the db (which I don't think is provided by any vendors…).Something akin to a subscriber/publisher design pattern, where I can subscribe to the DB from rails and say, "Notify me when anything to do with this row" has changed..
Like I don't understand why this is not a standard in any ORM implementation…
To me the idea of encapsulating a complete DB row as an object is meaningless if the underlying data can change at any time, and I can't tell until I try to save it. Like once I create that ActiveRecord object.. it's stale. So all calculations that I perform on those attributes of that object could well and truly be meaningless.
I would rather have it so that I am midway calculating the state of an object, and realise halfway that the underlying model has changed, so even before I attempt to save it I can rectify my calculations on the fly.
I'm assuming that when you say row locking thats pessimistic locking? Which is the other alternative which I will give a go as well, although I think on initial inspection has the possibility of deadlocking this particular scenario..
So that's actually my problem - I read a value and depend on that value, and so during the time of me calculating things with that value if it has changed, I need to know, but I can't until I have done my calculations, and find that value has changed when I try to save - but some instances, you don't even need to save.. you just do the calculation and pass that along.. which by that stage is incorrect.
Well as Korny was saying transactions and row locking won't help you if both data sets are valid.On 19/11/2010, at 9:04 AM, Dmytrii Nagirniak wrote:On 19 November 2010 08:47, Korny Sietsma <ko...@sietsma.com> wrote:
You should still think carefully about what it is you are trying to do.If you just catch the optimistic locking exception, and automatically reload and save, then you are ensuring the second user's change overwrites the first. The second user will never see the first user's change. That's not really optimistic locking at all.Yep. And this is how AR (basically most of ORMs) works by default - last wins. Nothing to do with the locking.Wondering why not just use a proper database transaction if atomicity is a requirement?
That's not even theoretically possible in a parallel system. All you
can do is code each
transaction semantically (add 1 to X rather than set X to old-X+1) and
then rely on
database serialisation to make it work. In order to reduce deadlocks,
you can use
intent-update locks (which AR's :lock gives you) or just ensure that
multi-record
updates are ordered (i.e. if you update A then B in one transaction,
you never update
B then A in another).
With long-polling or websockets, you could potentially notify the user
that the record
they're seeing has been updated, but you'd have to think that through
from a XP point
of view.
However, I don't think that's what Chris was concerned about. It seems
to me he was
worried that while I'm looking at some data and perhaps changing it,
but haven't yet
submitted my changes, someone else will submit a change that make my
changes
invalid. The correct answer is to detect that using versioning or row-
value checksums,
where the check value is hidden in the form I will submit, and must
match if my changes
are to be accepted.
The nice thing about doing this with checksums (as opposed to
versions) is that if the
record is large, and I'm only looking at a subset of the fields, I can
have a checksum
over just those fields, rather than the whole record. When I submit,
the record is re-fetched
and those fields re-checksummed. As long as *nothing I was looking at*
has changed,
my update is still valid. In most applications. YMMV. You might not
have encountered a
situation where this was even possible... but for example, the Claims
table in an insurance
app might well have a hundred fields, and those will never all be
shown at the same time.
You could break the record into separate records and use row versions
for each, but
then your UI is leaking into your schema.
Clifford Heath, Data Constellation, http://dataconstellation.com
Agile Information Management and Design
But the main problem for Chris is that the data is being updated while calculations are in progress. To avoid having stale objects, the transactions can be used.Of course, merging is totally different thing and is way more complicated. But as far as I understand Chris needs to ensure that there are no stale objects in the middle of an action (not user's one but a system's).
Also that MagLev is really cool! (http://www.vimeo.com/1147409)
On 19/11/2010, at 11:27 AM, Dmytrii Nagirniak wrote:That's not even theoretically possible in a parallel system.
But as far as I understand Chris needs to ensure that there are no stale objects in the middle of an action (not user's one but a system's).