01st jun 2009
O POG nosso de cada dia #9
Imagine que você tem uma área de administração no seu site onde você cria e edita algumas informações e persiste esses dados no banco. Acontece direto, né?
Se vocé esta editando os dados, o que você faz? Carrega do banco as informações e popula alguns campos (inputs, select, tabelas, textareas). Mas, e se você faz isso e tem alguém acessando essa mesma área de edição, e vai editar os mesmos dados que você ao mesmo tempo?
- Você carrega as informações na sua página
- Outra pessoa também carrega
- Você edita os campos e salva
- A outra pessoa edita e salva
Resultado: seus dados são perdidos
A solução bonita
O backend deveria controlar todo esse fluxo, e verifica se alguém está sobreescrevendo os dados do outro usuário – ou seja, o usuário 1 não sabe que aqueles dados já foram editados. E se isso ocorrer, devolve alguma informação para o usuário, indagando se ele deseja realmente sobreescrever os dados.
O problema
Tempo. Sempre tempo. Fazer esse controle demanda um bom tempo de programação no backend.
POG
Existe uma solução muito simples para isso, usando requisição via javascript ao servidor. Vale ressaltar que para essa solução, o registro que você vai editar deve ter um atributo que seja a data da última alteracão sofrida por ele.
O que pode ser feito: ao carregar os dados, pegue essa data da alteração (com dia, mês, ano, hora, minuto e segundo) e jogue num campo hidden. Quando for mandar atualizar os dados, é que vem o pulo-do-gato: transforme os dados desse hidden num Date do javascript, faça uma requisição ao servidor onde você recupera a data da última alteracão desse registro. No javascript, faça a comparação. Se a data que está gravada no banco for posterior a data que está naquele seu input, é porque alguém alterou esse registro após ele ter sido carregado na sua página, ou seja, você pode informar o usuário se quer ou não sobreescrever os dados.
Abaixo segue um exemplo de implementação da vida real, usando o framework DWR para fazer a requisição ao servidor.
var isBlocker = false;
dwr.engine.setAsync(false); //faz a requisição ser síncrona – trava o fluxo
//chama um método do backend que recebe um id e retorna a última data de edição desse registro
dbService.getLastEditionDate(id, {
callback:function(date) {
date.setSeconds(Math.floor(date.getSeconds()));
date.setMilliseconds(0);
var lastDate = new Date($F(“lastEditionDateInfo”)); //lastEditionDateInfo é o hidden que contém a data gravada
lastDate.setMilliseconds(0)
if(date>lastDate) {
if(!confirm(“Esse conteúdo foi alterado após o carregamento inicial. As alterações feitas fora dessa página serão sobreescritas.\nDeseja prosseguir?”)) {
isBlocker = true;
return false;
}
}
}
});
dwr.engine.setAsync(true);
if(isBlocker)
return false;
else
//continua o fluxo para editar

Não sei se isso seria um POG no meu conceito…
Para fazer isso backend, como você faria?
Pow, tá controlando na View o que tem que ser controlado no backend, Mathieu. É POG… hehe
O backend teria que saber (quem sabe guardando na sessão ou numa tabela auxiliar) quando a pessoa que está editando o registro o selecionou e comparia com a data da última atualização.
Logicamente essa implementação é muito mais custosa do que da forma que mostrei no post, mas ao meu ver é mais segura!
Eu concordo, eh um POG inteligente porém sem segurança por que nada impedi de um espertinho alterar a data do hidden que está no html, acho que como o chris disse uma session bastaria para resolver isso e caso queira fazer algo mais avançado ou até um histórico de alterações usar uma tabela.
Opa. passei batido na parte do hidden.
Tirando a parte do hidden, trocando por sessão ou tabela (dependendo da complexidade e do controle que voce quer ter) não seria mais um hidden.
Alias trocar o hidden para controle por sessões não me parece tão mais custosa.
Um POG até legal, podia ser usado para complementar A solução bonita
Todo POG tem seu lado bonito, Diogo! hehe
@Mathieu também não acho custoso, pois a quantidade de dados armazenados na sessão seria ínfima!
[...] #9: controle de edição de registros por usuários diferentes [...]