Forum: Rails France bloquer l'accès à une vue edit quand dé jà ouverte par un autre utilisateur

Posted by Florent Florent (Guest)
on 2010-03-16 16:47
(Received via mailing list)
Bonjour à tous,

Dans mon application, quand un utilisateur est en cours d'édition sur 
une
page (vue 'edit'), je souhaite empêcher (ou afficher un avertissement) 
un
autre utilisateur d'accéder à cette page d'édition (je préfère éviter 
une
solution prévenant l'écrasement de données seulement au moment où
l'utilisateur soumet les données de son formulaire).

Pour cela mon idée est de mettre un marqueur en base de données quand un
premier utilisateur accède à une page d'édition, et retirer ce marquer 
quand
il quitte cette page d'édition. Quand un utilisateur souhaite accéder à 
une
page d'édition, je le bloque si un tel marqueur existe pour cette page.

Mon problème est de détecter quand un utilisateur quitte une page en 
cours
d'édition, car il existe plusieurs façons pour un utilisateur de quitter
cette page : après une sauvegarde réussie, en suivant un lien vers une 
autre
page, quand il ferme la fenêtre d'édition dans son navigateur, quand il
ferme son navigateur... J'ai l'impression que c'est impossible en 
pratique
de détecter tous ces cas de figure et les reporter au serveur pour 
retirer
le marqueur.

Aussi pour détecter si un utilisateur est toujours sur sa vue edit, je 
pense
ajouter une information "date" aux marqueurs en BDD, et mettre un
periodically_call_remote dans mes vues edit qui rafraichirait la date du
marquer correspondant. Je ne bloquerais l'accès à une page d'édition 
pour un
autre utilisateur que si le marqueur correspondant a une date 
relativement
récente.

Ça me paraît faisable mais ça reste un peu alambiqué, aussi je suis 
ouvert à
toute suggestion pour simplifier cette implémentation voir utiliser une
autre façon de faire :)

Cordialement,
Florent
Posted by Michel Belleville (Guest)
on 2010-03-16 17:44
(Received via mailing list)
Bonjour Florent,

Sincèrement c'est la seule vraie solution pas trop moche à ton problème.

Cordialement,
Michel Belleville


2010/3/16 Florent Florent <florent2@gmail.com>
Posted by Guillaume Betous (Guest)
on 2010-03-16 18:14
(Received via mailing list)
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" 
http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
C'est ce que je pensais : en effet il n'y a que tr&egrave;s peu de 
lignes de
codes sp&eacute;cifiques en fait.<br>
<br>
Par contre, comme d'habitude, la solution passe parfois par la question
"ai-je vraiment besoin de &ccedil;a ?". Si tu estimes le cas possible 
(facile
: si tu as plusieurs utilisateurs, c'est toujours possible) mais peu
probable, tu peux te limiter &agrave; d&eacute;tecter le 
probl&egrave;me, mais &agrave; ne pas le
corriger.<br>
<br>
Par exemple, quand tu entres en &eacute;dition, tu lis la version de
l'enregistrement. Juste avant de sauver, tu v&eacute;rifie qu'il n'a pas
boug&eacute;. si il a boug&eacute; entre temps, tu te limites &agrave; 
dire "enregistrement
modifi&eacute; par ailleurs, je refuse d'&eacute;craser", et c'est aux 
utiliteurs de
se d&eacute;brouiller.<br>
<br>
C'est &eacute;videmment bcp plus sommaire comme solution, mais si 
&ccedil;a suffit &agrave;
ton cas (sans compter le fait d'&ecirc;tre ind&eacute;pendant de 
Javascript...)<br>
<br>
gUI<br>
<br>
Michel Belleville a &eacute;crit&nbsp;:
<blockquote
 cite="mid1b21f5871003160942q19a964fel75cea71d0c40baf5@mail.gmail.com"
 type="cite">Bonjour Florent,<br>
  <br>
Sinc&egrave;rement c'est la seule vraie solution pas trop moche &agrave; 
ton probl&egrave;me.<br>
  <br>
Cordialement,<br clear="all">
Michel Belleville<br>
  <br>
  <br>
  <div class="gmail_quote">2010/3/16 Florent Florent <span 
dir="ltr">&lt;<a
 href="mailto:florent2@gmail.com">florent2@gmail.com</a>&gt;</span><br>
  <blockquote class="gmail_quote"
 style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 
0.8ex; padding-left: 1ex;">
    <div>Bonjour &agrave; tous,</div>
    <div><br>
    </div>
    <div>Dans mon application, quand un utilisateur est en cours
d'&eacute;dition sur une page (vue 'edit'), je souhaite emp&ecirc;cher 
(ou afficher
un avertissement) un autre utilisateur d'acc&eacute;der &agrave; cette 
page d'&eacute;dition
(je pr&eacute;f&egrave;re &eacute;viter une solution pr&eacute;venant 
l'&eacute;crasement de donn&eacute;es
seulement au moment o&ugrave; l'utilisateur soumet les donn&eacute;es de 
son
formulaire).</div>
    <div><br>
    </div>
    <div>Pour cela mon id&eacute;e est de mettre un marqueur en base de
donn&eacute;es quand un premier utilisateur acc&egrave;de &agrave; une 
page d'&eacute;dition, et
retirer ce marquer quand il quitte cette page d'&eacute;dition. Quand un
utilisateur souhaite acc&eacute;der &agrave; une page d'&eacute;dition, 
je le bloque si un
tel marqueur existe pour cette page.</div>
    <div><br>
    </div>
    <div>Mon probl&egrave;me est de d&eacute;tecter quand un utilisateur 
quitte une
page en cours d'&eacute;dition, car il existe plusieurs fa&ccedil;ons 
pour un
utilisateur de quitter cette page : apr&egrave;s une sauvegarde 
r&eacute;ussie, en
suivant un lien vers une autre page, quand il ferme la fen&ecirc;tre
d'&eacute;dition dans son navigateur, quand il ferme son navigateur... 
J'ai
l'impression que c'est impossible en pratique de d&eacute;tecter tous 
ces cas
de figure et les reporter au serveur pour retirer le marqueur.</div>
    <div><br>
    </div>
    <div>Aussi pour d&eacute;tecter si un utilisateur est toujours sur 
sa vue
edit, je pense ajouter une information "date" aux marqueurs en BDD, et
mettre un periodically_call_remote dans mes vues edit qui rafraichirait
la date du marquer correspondant. Je ne bloquerais l'acc&egrave;s 
&agrave; une page
d'&eacute;dition pour un autre utilisateur que si le marqueur 
correspondant a
une date relativement r&eacute;cente.</div>
    <div><br>
    </div>
    <div>&Ccedil;a me para&icirc;t faisable mais &ccedil;a reste un peu 
alambiqu&eacute;, aussi je
suis ouvert &agrave; toute suggestion pour simplifier cette 
impl&eacute;mentation
voir utiliser une autre fa&ccedil;on de faire :)</div>
    <div><br>
    </div>
    <div>Cordialement,</div>
    <div>Florent</div>
-- <br>
    <font color="#888888">Vous avez re&ccedil;u ce message, car vous 
&ecirc;tes
abonn&eacute; au groupe "Railsfrance" de Google Groups.<br>
Pour transmettre des messages &agrave; ce groupe, envoyez un e-mail 
&agrave;
l'adresse <a href="mailto:railsfrance@googlegroups.com" 
target="_blank">railsfrance@googlegroups.com</a><br>
Pour r&eacute;silier votre abonnement envoyez un e-mail &agrave; 
l'adresse <a
 href="mailto:railsfrance-unsubscribe@googlegroups.com" 
target="_blank">railsfrance-unsubscribe@googlegroups.com</a></font></blockquote>
  </div>
  <br>
-- <br>
Vous avez re&ccedil;u ce message, car vous &ecirc;tes abonn&eacute; au 
groupe "Railsfrance"
de Google Groups.<br>
Pour transmettre des messages &agrave; ce groupe, envoyez un e-mail 
&agrave;
l'adresse <a class="moz-txt-link-abbreviated" 
href="mailto:railsfrance@googlegroups.com">railsfrance@googlegroups.com</a><br>
Pour r&eacute;silier votre abonnement envoyez un e-mail &agrave; 
l'adresse
<a class="moz-txt-link-abbreviated" 
href="mailto:railsfrance-unsubscribe@googlegroups.com">railsfrance-unsubscribe@googlegroups.com</a>
</blockquote>
</body>
</html>

<p></p>

-- <br />
Vous avez reçu ce message, car vous êtes abonné au groupe 
&quot;Railsfrance&quot; de Google Groups.<br />
Pour transmettre des messages à ce groupe, envoyez un e-mail à l&#39;adresse 
railsfrance@googlegroups.com<br />
Pour résilier votre abonnement envoyez un e-mail à l&#39;adresse 
railsfrance-unsubscribe@googlegroups.com
Posted by Florent Florent (Guest)
on 2010-03-18 02:57
(Received via mailing list)
Le 16 mars 2010 12:01, Guillaume Betous <guillaume.betous@gmail.com> a 
écrit
:

> il a bougé entre temps, tu te limites à dire "enregistrement modifié par
> ailleurs, je refuse d'écraser", et c'est aux utiliteurs de se débrouiller.
>
> C'est évidemment bcp plus sommaire comme solution, mais si ça suffit à ton
> cas (sans compter le fait d'être indépendant de Javascript...)
>


Merci Michel & Guillaume pour vos réponses ! Après consultation des
utilisateurs de l'appli, ta solution Guillaume leur suffit. Du coup 
c'est
celle que j'ai retenue car c'est plus simple à implémenter.

Cordialement,
Florent
Posted by Guillaume Betous (Guest)
on 2010-03-18 07:42
(Received via mailing list)
> Merci Michel & Guillaume pour vos réponses ! Après consultation des
> utilisateurs de l'appli, ta solution Guillaume leur suffit. Du coup c'est
> celle que j'ai retenue car c'est plus simple à implémenter.
>

Attention, il faut que tu rendes atomique (c'est à dire ininterruptible)
l'action "je relis pour vérifier que l'enregistrement n'a pas bougé puis 
je
savue une nouvelle version". Je crois que c'est le concept des 
transactions
[1] (je l'ai jamais mis en oeuvre mais j'y avais jeté un oeil pour un 
projet
perso).

Sinon tu risques le scénario suivant :
A lit l'enregistrement en version x
A édite l'enregistrement
B lit l'enregistrement en version x
B edite l'enregistrement
A vérifie l'enregistrement toujours en x => OK
B vérifie l'enregistrement toujours en x => OK
A sauve et passe en version x+1
B écrase la sauvegard de A et passe aussi en x+1

gUI

[1]
http://api.rubyonrails.org/classes/ActiveRecord/Tr...

--
Pour la santé de votre ordinateur, préférez les logiciels libres.
Lire son mail : http://www.mozilla-europe.org/fr/products/thunderbird/
Browser le web : http://www.mozilla-europe.org/fr/products/firefox/
Suite bureautique : http://fr.openoffice.org/
Posted by Florent Florent (Guest)
on 2010-03-19 14:54
(Received via mailing list)
Le 18 mars 2010 02:41, Guillaume Betous <guillaume.betous@gmail.com> a 
écrit
:

> perso).
>
> gUI
>
> [1]
> http://api.rubyonrails.org/classes/ActiveRecord/Tr...
>
>

Effectivement, je n'avais pas pensé à ce cas, merci Guillaume. J'ai 
consulté
la page de l'API que tu as pointée, elle dit :

"Both Base#save and Base#destroy come wrapped in a transaction that 
ensures
that whatever you do in validations or callbacks will happen under the
protected cover of a transaction."

J'ai implémenté sous forme de validation la vérification qu'un
enregistrement est toujours en version x, donc si je comprends bien le 
texte
la vérification et la sauvegarde ont lieu dans une même transaction.

Même si ce n'est pas le cas, je crois que je vais passé outre le cas de
figure du problème d'un enregistrement (quasi) simultané par 2 
utilisateurs,
car dans mon application les fréquences d'enregistrement sont faibles.

Florent

--
Vous avez reçu ce message, car vous êtes abonné au groupe "Railsfrance" 
de Google Groups.
Pour transmettre des messages à ce groupe, envoyez un e-mail à l'adresse 
railsfrance@googlegroups.com
Pour résilier votre abonnement envoyez un e-mail à l'adresse 
railsfrance-unsubscribe@googlegroups.com

To unsubscribe from this group, send email to 
railsfrance+unsubscribegooglegroups.com or reply to this email with the 
words "REMOVE ME" as the subject.
Posted by David Bourguignon (Guest)
on 2010-04-07 12:38
(Received via mailing list)
Bonjour,

j'arrive un peu tard, mais Rails implémente ça directement :
http://apidock.com/rails/ActiveRecord/Locking/Optimistic

++
David

Le 19 mars 2010 14:53, Florent Florent <florent2@gmail.com> a écrit :

>> l'action "je relis pour vérifier que l'enregistrement n'a pas bougé puis je
>> B vérifie l'enregistrement toujours en x => OK
> Effectivement, je n'avais pas pensé à ce cas, merci Guillaume. J'ai
> Même si ce n'est pas le cas, je crois que je vais passé outre le cas de
> Pour résilier votre abonnement envoyez un e-mail à l'adresse
> railsfrance-unsubscribe@googlegroups.com
>
> To unsubscribe from this group, send email to railsfrance+
> unsubscribegooglegroups.com or reply to this email with the words "REMOVE
> ME" as the subject.
>

--
Vous avez reçu ce message, car vous êtes abonné au groupe "Railsfrance" 
de Google Groups.
Pour transmettre des messages à ce groupe, envoyez un e-mail à l'adresse 
railsfrance@googlegroups.com
Pour résilier votre abonnement envoyez un e-mail à l'adresse 
railsfrance-unsubscribe@googlegroups.com

To unsubscribe, reply using "remove me" as the subject.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.