Permalink
Browse files

adding destroy config section and support for custom destroy methods …

…on models
  • Loading branch information...
1 parent a8f20fa commit fa48e166dad1129b8f7407c6b765839832541490 @snmgian snmgian committed Mar 17, 2011
View
@@ -20,3 +20,4 @@ spec/dummy_app/log/*.log
tmp/**/*
/.emacs.desktop
.idea/*.xml
+*~
View
@@ -809,6 +809,21 @@ accomplished like this:
end
end
+**Soft destroys**
+
+When the admin interface deletes an object it invokes the destroy method on the object. But if another method must be invoked instead of destroy one can assign a configuration to achieve that:
+
+
+ RailsAdmin.config do |config|
+ config.model Team do
+ destroy do
+ soft_destroy :custom_destroy
+ end
+ end
+ end
+
+If the soft_destroy configuration receives `true` instead of a `:symbol`, the method soft_destroy will be invoked by default.
+
Authorization
-------------
@@ -120,7 +120,7 @@ def delete
def destroy
@authorization_adapter.authorize(:destroy, @abstract_model, @object) if @authorization_adapter
- @object = @object.destroy
+ @object = destroy_object
flash[:notice] = t("admin.delete.flash_confirmation", :name => @model_config.list.label)
AbstractHistory.create_history_item("Destroyed #{@model_config.list.with(:object => @object).object_label}", @object, @abstract_model, _current_user)
@@ -141,7 +141,7 @@ def bulk_destroy
@authorization_adapter.authorize(:bulk_destroy, @abstract_model) if @authorization_adapter
scope = @authorization_adapter && @authorization_adapter.query(params[:action].to_sym, @abstract_model)
- @destroyed_objects = @abstract_model.destroy(params[:bulk_ids], scope)
+ @destroyed_objects = bulk_destroy_objects(params[:bulk_ids], scope)
@destroyed_objects.each do |object|
message = "Destroyed #{@model_config.list.with(:object => object).object_label}"
@@ -165,6 +165,38 @@ def handle_error(e)
private
+ # Destroy an object selecting the destroy strategy
+ def destroy_object
+ soft_destroy_method = get_soft_destroy_method
+
+ if soft_destroy_method
+ @object.send soft_destroy_method
+ else
+ @object.destroy
+ end
+ end
+
+ # Destroy bulk objects selecting the destroy strategy
+ def bulk_destroy_objects bulk_ids, scope
+ soft_destroy_method = get_soft_destroy_method
+
+ if soft_destroy_method
+ @destroyed_objects = bulk_soft_destroy(scope, bulk_ids, soft_destroy_method)
+ else
+ @destroyed_objects = @abstract_model.destroy(bulk_ids, scope)
+ end
+ end
+
+ # Performs a soft_destroy on the objects whose IDs are present in the bulk_ids array
+ def bulk_soft_destroy scope, bulk_ids, soft_destroy_method
+ scope ||= @abstract_model.model
+ scope = scope.where(:id => bulk_ids)
+ scope.to_a.each do |object|
+ object.send soft_destroy_method
+ end
+ end
+
+
def get_bulk_objects
scope = @authorization_adapter && @authorization_adapter.query(params[:action].to_sym, @abstract_model)
@bulk_ids = params[:bulk_ids]
@@ -239,6 +271,28 @@ def get_attributes
end
end
+ # If soft_destroy is configured as a Symbol it invokes a method with that name
+ # If soft_destory is not a Symbol it invokes soft_destroy method
+ # Else invokes destroy method
+ def get_soft_destroy_method
+ soft_destroy = @model_config.destroy.soft_destroy
+
+ method = nil
+ if Symbol === soft_destroy
+ method = soft_destroy
+
+ elsif soft_destroy
+ method = :soft_destroy
+ end
+
+ if method
+ return method if @abstract_model.model.instance_methods.include? method
+ raise NoMethodError.new("#{@object} has no method #{soft_destroy}")
+ else
+ return nil
+ end
+ end
+
def redirect_to_on_success
param = @abstract_model.to_param
pretty_name = @model_config.update.label
@@ -40,7 +40,7 @@ def edit(&block)
# store the configurations.
def method_missing(m, *args, &block)
responded_to = false
- [:create, :list, :navigation, :update].each do |s|
+ [:create, :destroy, :list, :navigation, :update].each do |s|
section = send(s)
if section.respond_to?(m)
responded_to = true
@@ -1,5 +1,6 @@
require 'active_support/core_ext/string/inflections'
require 'rails_admin/config/sections/create'
+require 'rails_admin/config/sections/destroy'
require 'rails_admin/config/sections/list'
require 'rails_admin/config/sections/navigation'
require 'rails_admin/config/sections/update'
@@ -0,0 +1,16 @@
+require 'rails_admin/config/base'
+
+module RailsAdmin
+ module Config
+ module Sections
+ # Configuration of the destroy view
+ class Destroy < RailsAdmin::Config::Base
+
+ # Defines if the objects will be destroyed using a custom_method
+ register_instance_option(:soft_destroy) do
+ false
+ end
+ end
+ end
+ end
+end
@@ -0,0 +1,12 @@
+class Club < ActiveRecord::Base
+ validates_presence_of(:name)
+
+ def custom_destroy
+ update_attribute(:disabled, true)
+
+ @destroyed = true
+ freeze
+ end
+end
+
+
@@ -0,0 +1,11 @@
+class Coach < ActiveRecord::Base
+ validates_presence_of(:name)
+
+ def soft_destroy
+ update_attribute(:disabled, true)
+
+ @destroyed = true
+ freeze
+ end
+end
+
@@ -1,3 +1,16 @@
RailsAdmin.config do |c|
c.excluded_models << RelTest
+
+ c.model Coach do
+ destroy do
+ soft_destroy true
+ end
+ end
+
+ c.model Club do
+ destroy do
+ soft_destroy :custom_destroy
+ end
+ end
+
end
@@ -0,0 +1,14 @@
+class CreateCoachesMigration < ActiveRecord::Migration
+ def self.up
+ create_table :coaches do |t|
+ t.string :name
+ t.boolean :disabled
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :coaches
+ end
+end
@@ -0,0 +1,14 @@
+class CreateClubsMigration < ActiveRecord::Migration
+ def self.up
+ create_table :clubs do |t|
+ t.string :name
+ t.boolean :disabled
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :clubs
+ end
+end
@@ -64,4 +64,56 @@
RailsAdmin::AbstractModel.new("Player").count.should == 3
end
end
+
+ describe "soft_bulk_destroy" do
+ before(:each) do
+ RailsAdmin::History.destroy_all
+
+ to_delete = []
+ to_delete << RailsAdmin::AbstractModel.new("Coach").create(:name => 'Coach 1')
+ to_delete << RailsAdmin::AbstractModel.new("Coach").create(:name => 'Coach 2')
+
+ @delete_ids = to_delete.map(&:id)
+ get rails_admin_bulk_delete_path(:model_name => "coach", :bulk_ids => @delete_ids)
+
+ click_button "Yes, I'm sure"
+ @coaches = RailsAdmin::AbstractModel.new("Coach").all
+ end
+
+ it "should be successful" do
+ response.should be_successful
+ end
+
+ it "should disable the objects" do
+ @coaches.each do |coach|
+ coach.disabled.should eql(true)
+ end
+ end
+ end
+
+ describe "soft_bulk_destroy_with_custom_method" do
+ before(:each) do
+ RailsAdmin::History.destroy_all
+
+ to_delete = []
+ to_delete << RailsAdmin::AbstractModel.new("Club").create(:name => 'Club 1')
+ to_delete << RailsAdmin::AbstractModel.new("Club").create(:name => 'Club 2')
+
+ @delete_ids = to_delete.map(&:id)
+ get rails_admin_bulk_delete_path(:model_name => "club", :bulk_ids => @delete_ids)
+
+ click_button "Yes, I'm sure"
+ @clubs = RailsAdmin::AbstractModel.new("Club").all
+ end
+
+ it "should be successful" do
+ response.should be_successful
+ end
+
+ it "should disable the objects" do
+ @clubs.each do |club|
+ club.disabled.should eql(true)
+ end
+ end
+ end
end
@@ -50,4 +50,41 @@
end
end
+ describe "soft_destroy" do
+ before(:each) do
+ @coach = RailsAdmin::AbstractModel.new("Coach").create(:name => "Coach 1")
+
+ get rails_admin_delete_path(:model_name => "coach", :id => @coach.id)
+
+ @req = click_button "Yes, I'm sure"
+ @coach = RailsAdmin::AbstractModel.new("Coach").first
+ end
+
+ it "should be successful" do
+ @req.should be_successful
+ end
+
+ it "should disable an object" do
+ @coach.disabled.should eql(true)
+ end
+ end
+
+ describe "soft_destroy_with_custom_method" do
+ before(:each) do
+ @club = RailsAdmin::AbstractModel.new("Club").create(:name => "Club 1")
+
+ get rails_admin_delete_path(:model_name => "club", :id => @club.id)
+
+ @req = click_button "Yes, I'm sure"
+ @club = RailsAdmin::AbstractModel.new("Club").first
+ end
+
+ it "should be successful" do
+ @req.should be_successful
+ end
+
+ it "should disable an object" do
+ @club.disabled.should eql(true)
+ end
+ end
end

2 comments on commit fa48e16

Owner

sferik replied Mar 29, 2011

Looks like there was some code in this commit which only works in Ruby 1.9.2: http://ci.railsadmin.org/job/RailsAdmin/186/

Owner

sferik replied Mar 29, 2011

Reverted in d4ca29d.

Please sign in to comment.