Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I have a flash message in active admin when destroy failed?

In my app, some resources cannot be destroyed. So I wrote my model like this:

before_destroy :destroy_check
def destroy_check
  if some_reason?
    errors.add(:base, 'cannot destroy this resource!')
  end
  errors.blank?
end

Then, when I click destroy button in ActiveAdmin, there is nothing to show: no error, no message, and the record is not really destroyed. How can I show an error message when destroy fails?

like image 278
WilliamZang Avatar asked Jan 25 '14 16:01

WilliamZang


3 Answers

First use your model's before_destroy callback to check if the record can be destroyed (here if a student is signed in):

class Student < ActiveRecord::Base
  before_destroy :before_destroy_check_for_groups

  def before_destroy_check_for_groups   
    if StudentInGroup.exists?(student_id: self.id)
      errors.add(:base, I18n.t('app.student_signed_in'))
      return false   
    end 
  end
end

It's common and easy and you do it for each model you want.

And here is a trick. You may apply a general patch for all Active Admin resources to pass your model's error message to the user as a ResourceController's callback. It's the check_model_errors method below. And this method has to be registered as a callback during execution of each resource's ActiveAdmin.register method call (see the patched run_registration_block). You may simply paste the code below to a new file (of any name) to the config/initializers folder of your app (or any other folder which is initialized upon app startup). I put it as config/initializers/active_admin_patches.rb.

class ActiveAdmin::ResourceController
  def check_model_errors(object)
      return unless object.errors.any?
      flash[:error] ||= []
      flash[:error].concat(object.errors.full_messages)
  end
end
class ActiveAdmin::ResourceDSL
  alias_method :old_run_registration_block, :run_registration_block
  def run_registration_block(&block)
    old_run_registration_block(&block)
    instance_exec { after_destroy :check_model_errors }
  end
end
like image 63
Jakub Avatar answered Nov 04 '22 04:11

Jakub


I found this can be accomplished within ActiveAdmin through I18n translations and customizing the Responders' Interpolation Options in the controller.

Adding the method #interpolation_options to ActiveAdmin::BaseController in an initializier:

# config/initializers/active_admin.rb
class ActiveAdmin::BaseController
  private

  def interpolation_options
    options = {}

    options[:resource_errors] =
      if resource && resource.errors.any?
        "#{resource.errors.full_messages.to_sentence}."
      else
        ""
      end

    options
  end
end

Then overriding the translation for the destroy alert message in the locale file:

# config/locales/en.yml
en:
  flash:
    actions:
      destroy:
        alert: "%{resource_name} could not be destroyed. %{resource_errors}"
like image 7
Charles Maresh Avatar answered Nov 04 '22 04:11

Charles Maresh


if you want to be a resource that has not been removed from the active admin:

ActiveAdmin.register SomeModel do
  controller do        
    def destroy
      flash[:notice] = 'Cant delete this!'
      redirect_to :back
    end        
  end
end

or delete actions:

ActiveAdmin.register SomeModel do
  actions :all, except: [:destroy]
end
like image 3
Philidor Avatar answered Nov 04 '22 04:11

Philidor