Fork me on GitHub Fork me on GitHub

Blog do Kiva

As aventuras de um tal Kivanio na TI

Rails for Kids 2009

Plugin ActsAsDeleted para não apagar

18/08/2008

 Acabo de disponibilizar outro plugin, o ActsAsDeleted.

Este plugin serve para que seus registros não sejam apagados do banco.

Mas como assim não apagar?

Certas aplicações necessitam que seus dados não sejam apagados quando um usuário aperta um botão delete, como é o caso no meu projeto atual, onde trabalho com muitos registros financeiros.

Estes dados simplesmente não aparecem mais no sistema, por questões de segurança, de auditoria ou simplesmente porque seu chefe quer assim.

Este plugin disponibiliza métodos para que isso seja possível facilmente, sem a necessidade de ficar criando métodos, inserindo nos models e etc.

Tudo em um só local, cool, DRY ;)

Sim existem 2 outros plugins(só achei  dois),

o acts_as_paranoid 

e o acts_as_soft_deletable

O segundo não me agradou por trabalhar com uma tabela a mais somente para guardar os registros apagados, eu prefiro tê-los na mesma tabela.

O primeiro é muito bom, trabalha com apenas um campo datetime e segue quase a mesma forma que o meu.

Porém tive alguns problemas com validação conforme explico no fim do tutorial, não sei se por que não consegui utilizar direito ou por falha do plugin, entre outras coisas que não me atendiam.

Editado - OBS: cometi um engano, o acts_as_paranoid faz validação sim, usando a mesma opção :scope é possível conseguir a validação

Eu precisava de um campo de flag que não fosse uma data, até para mostrar em possível recuperação de registro na tela do administrador, além de um campo para guardar o usuário que fez a cagada, ops, apagou o registro :D

Enfim nasceu o rebento.

Fonte no github: ActsAsDeleted

Um tutozinho:

REQUER Rails >= 2.1 

 

Instalando o plugin:

script/plugin install git://github.com/kivanio/acts_as_deleted.git

 

Exemplo

=======

 

Em sua migration:

 

class CreateCars < ActiveRecord::Migration

  def self.up

    create_table :cars do |t|

      t.string :name

      # Use "deletestamps" para criar as colunas "deleted" e "deleted_at"

      # Passando o argumento "true", será criada a coluna "deleted_id" para usar com o plugin restful-authentication

      t.deletestamps(true)

      t.timestamps

    end

  end

 

  def self.down

    drop_table :cars

  end

end

 

Em seu model:

class Car < ActiveRecord::Base

  acts_as_deleted

end

 

Depois disso em seu Controller:

class CarController < ApplicationController

  # Use o scope "without_deleted" para procurar por registros que não estão marcados como deletados.

  def index

    @cars = Car.without_deleted.find :all

  end

  # Use o scope "with_deleted" para procurar por registros marcados como deletados.

  def all

    @cars = Car.with_deleted.find :all

  end

 

  #Use apenas find para todos os registros

  def all

    @cars = car.find :all

  end

  # Em sua action destroy use o método "delete" para esconder os registros

  def destroy

   @car = Car.find(params[:id])

    if @car.delete

      flash[:notice] = 'Bye Bye Car.'

    end

    redirect_to(cars_url)

  end

  # Quando você estiver usando o plugin restful-authentication, você pode usa "delete_with_user" para gravar o usuário que apagou o registro.

  def destroy_with_user

     @car = Car.find(params[:id])

      if @car.delete_with_user(current_user.id)

        flash[:notice] = 'Bye Bye Car.'

      end

      redirect_to(cars_url)

    end

end

 

Dicas:

Para usar o validates_uniqueness_of  com este plugin, você deve usar a opção :scope do validates_uniqueness_of.

validates_uniqueness_of :name, :scope => :deleted

Será validado então "name AND deleted" ao invés de apenas "name",

assim você terá ter vários registros apagados com mesmo nome, porém apenas um não apagado com este nome.

 

 

Bem simples!

 

Gostou?

Recomende-me: http://www.workingwithrails.com/recommendation/new/person/5679-kivanio-pereira-barbosa

 

 





Comentários

Mereghost
postado em 18/08/2008 20:35:35

Fala Kiva! Então, só uma sugestão: faz um alias (pra não quebrar nada de alguém que está usando) dos nomes dos scopes. with_deleted/without_deleted para deleted/not_deleted Senão fica meio estranho "com_apagado", "sem apagado". ;)

Kivanio
postado em 18/08/2008 20:41:01

Grande Mereghost, valeu pela dica, nem havia pensado nestes detalhes, como não havia quebrado comigo ainda, acabei esquecendo que alguém podia estar usando estes nomes.

Clovis
postado em 18/08/2008 21:20:27

Ainda não olhei seu plugin.. mas eu tinha visto outro similar.. Act as Audited! :) http://opensoul.org/2006/07/21/acts_as_audited

Davis
postado em 18/08/2008 22:57:07

Kivanio, Será que não vale um patch no acts_as_paranoid? Abraço!

Rodrigo Toledo
postado em 19/08/2008 01:49:38

Kivano, mandou bem. Mas assim, uma dúvida. Quer dizer que o Model.find(:all) Retorna todos, inclusive os que estão excluídos? Caso sim, seria um certo problema para aplicações que já estão rodando.. concorda? Pensa assim... tem find(:all) pra tudo que é lado nas aplicações que estão rodando.

Kivanio
postado em 19/08/2008 01:53:49

Clovis, este plugin é para outro fim, ele apenas loga quem fez o oque, mas não impede, nem fornece métodos que impeçam o registro de ser apagado, existe um melhor na minha opinião o "UserStamps", procure por ele no github.

Kivanio
postado em 19/08/2008 01:56:02

Davis, A grande questão é que ele tem outro foco, ele usa um campo datetime, apenas pra saber se já foi apagado. Mudar isso nele seria refazer o plugin, o que não vejo como opção, pois ele me parece ser para coisas mais simples. No caso em que eu estou citando, ele não serve, eu preciso de outras coisas que ele não fornece, como a compatibilidade com o plugin de autenticação, acredite eu tentei utilizá-lo, mas realmente não deu.

Kivanio
postado em 19/08/2008 02:01:03

Rodrigo Toledo, eu não implementei o find :all, foi apenas um exemplo para você usar sem os scopos, quando quiser tudo idependente do filtro do scopo. Só existem dois scopos, que você pode inserir antes do find :all, caso queria buscar com ou sem os registros apagados. Sobrescrever o find para ficar automático, talvez seja uma boa idéia, porém a princípio, penso que apenas um scopo na busca seja menos intrusivo.

Kivanio
postado em 19/08/2008 02:14:53

OBS: cometi um engano, o acts_as_paranoid faz validação sim, usando a mesma opção :scope é possível conseguir a validação.

Arthur
postado em 19/08/2008 14:12:29

O plugin funciona para aplicações na versão 1.2.6 do Rails?

Mereghost
postado em 19/08/2008 16:18:36

Arthur: Provavelmente não, já que usa named_scopes que não existem no Rails 1.2.6.

Kivanio
postado em 19/08/2008 17:42:01

Arthur, como disse o Mereghost, só a partir da versão 2.1 do rails, versões anteriores, somente com o acts_as_paranoid

Comentar artigo

Campos em negrito são obrigatórios.


 
< Voltar