Showing posts with label rails. Show all posts
Showing posts with label rails. Show all posts

Wednesday, 22 February 2017

[SOLVED] Rails multiple databases not cleaning up in tests.

So the other day I was facing this issue with Rails where the data created in a test would not get deleted from my secondary database.

The database was not cleaning up after the first test. the order didn’t matter. which ever test runs first the records created in that block were not deleted. after thorough debugging i found that there is a block inside actived record which rollsback the db. here is that block (https://github.com/rails/rails/blob/master/activerecord/lib/active_record/fixtures.rb#L1008).

 So in case of the first test the @fixture_connections count is 1 it only contains the primary db connection.

So for my secondary db I had created an abstract class SecondaryModel  which inherited from  ActiveRecord::Base 
So adding SecondaryModel.connection to test_helper solved this problem.

hope this helped!

Wednesday, 10 August 2016

How to set flash error when devise reset password token is expired in Active Admin

So I was facing this issue a while ago when I wanted to show an error on Active Admin when the password token is expired. By default devise doesn't show error when the token is expired. check the below devise update code

  # PUT /resource/password
  def update
    self.resource = resource_class.reset_password_by_token(resource_params)
    yield resource if block_given?
    if resource.errors.empty?
      resource.unlock_access! if unlockable?(resource)
      if Devise.sign_in_after_reset_password
        flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
        set_flash_message(:notice, flash_message) if is_flashing_format?
        sign_in(resource_name, resource)
      else
        set_flash_message(:notice, :updated_not_active) if is_flashing_format?
      end
      respond_with resource, location: after_resetting_password_path_for(resource)
    else
      set_minimum_password_length
      respond_with resource
    end
  end

So as you can see if the condition resource.errors.empty?  is false it does not set any errors in the else block.
So one way to solve this is to override the whole method and add flash[:error] in the else block like this

ActiveAdmin::Devise::PasswordsController.class_eval do
  def update
    self.resource = resource_class.reset_password_by_token(resource_params)
    yield resource if block_given?

    if resource.errors.empty?
      resource.unlock_access! if unlockable?(resource)
      if Devise.sign_in_after_reset_password
        flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
        set_flash_message(:notice, flash_message) if is_flashing_format?
        sign_in(resource_name, resource)
      else
        set_flash_message(:notice, :updated_not_active) if is_flashing_format?
      end
      respond_with resource, location: after_resetting_password_path_for(resource)
    else
      flash[:error] = resource.errors.full_messages.to_sentence
      set_minimum_password_length
      respond_with resource
    end
  end
end

but this is not a very smart way to handle this as I am repeating a lot of the code. so I thought of another DRY way to do this

ActiveAdmin::Devise::PasswordsController.class_eval do
  def update
    super
    if resource.errors.any?
      flash[:error] = resource.errors.full_messages.to_sentence
    end
  end
end

Although this looks fine but it doesn't work as the flash message is shown in the next request.
after a while of searching here and there my eye caught the following code in the devise method

yield resource if block_given?

 and here is the solution I came up with.

ActiveAdmin::Devise::PasswordsController.class_eval do
  def update
    super do |resource|
      if resource.errors.any?
        flash[:notice] = resource.errors.full_messages.to_sentence
      end
    end
  end
end

Hope it helped :)