0

I have a multitenancy app and I'm setting the current tenancy like this:

class ApplicationController < ActionController::Base
  around_filter :scope_current_tenancy

  def scope_current_tenancy
    Tenancy.current_id = current_tenancy.id if request.subdomain != 'www'
    yield
  ensure
    Tenancy.current_id = nil
  end
end

Then in my user model I have a default_scope defined to access only to users within my tenancy:

class Postulant < ActiveRecord::Base

  default_scope ->{ where("enlistments.tenancy_id = ?", Tenancy.current_id).includes(:enlistments).references(:enlistments) }

This works so far, but now using devise_invitable and trying to accept an invitation I'm receiving a Filter chain halted as :resource_from_invitation_token rendered or redirected message. The problem is because my scope_current_tenancy filter is being executed after resource_from_invitation_token, so resource is not loading correctly.

class Devise::InvitationsController < DeviseController

  prepend_before_filter :resource_from_invitation_token, :only => [:edit, :destroy]

  def resource_from_invitation_token
    # Here 'resource_class' is my Postulant model, so when I call
    # 'find_by_invitation_token' applies the defined default_scope
    # which doesn't word without 'scope_current_tenancy'
    unless params[:invitation_token] && self.resource = resource_class.find_by_invitation_token(params[:invitation_token], true)
      set_flash_message(:alert, :invitation_token_invalid)
      redirect_to after_sign_out_path_for(resource_name)
    end
  end

end

So my question is, is there a way to run :scope_current_tenancy before than :resource_from_invitation_token?
I've tried to change around_filter :scope_current_tenancy to prepend_around_filter :scope_current_tenancy but I had no luck. Any thoughts?

Alter Lagos
  • 12,090
  • 1
  • 70
  • 92

1 Answers1

1

Because the prepend_before_filter :resource_from_invitation_token comes after your ApplicationController, this filter will be prepended to the front of the filter chain, even if you use prepend_before_filter for scope_current_tenancy. One option might be to try something like:

skip_around_filter :scope_current_tenancy
prepend_before_filter :resource_from_invitation_token, :only => [:edit, :destroy]
prepend_around_filter :scope_current_tenancy

in your Devise::InvitationsController

Not sure if this will work, but seems worth a shot.

Alternately, you could just drop the 'skip_around_filter' line, assuming the scope_current_tenancy is idempotent, which seems to be the case.

Peter Goldstein
  • 4,479
  • 2
  • 19
  • 17
  • It worked, but I'm worried that I should implement this solution to each devise controller, creating my own versions of those controllers, at least where is used `prepend_before_filter`. It would be great a generic way to do this – Alter Lagos Nov 20 '13 at 16:47
  • You may be able to do something more elegant, especially if the `skip_before_filter` is optional, in which case you can just include a module with the `prepend_around_filter :scope_current_tenancy` for each of the Devise controllers in an initializer. But otherwise I think you may need to handle it this way for each controller that prepends to the filter chain. – Peter Goldstein Nov 20 '13 at 16:52