betacar
betacar

Reputation: 426

Set a current_profile for a user

A user can has many profiles. Each profile has its own properties. And the user can change from one profile to another anytime, anywhere.

So I want to set a method or variable available in controllers and views where I can set the user's current_profile (like devise's current_user helper).

We've tried using a ApplicationController private method and a ApplicationHelper method, but it doesn't work when the user's nickname it's not available (is set through a URL param).

This is the AppController method

...
private
  def set_profile
    if params[:username]
      @current_profile ||= Profile.where(username: params[:username]).entries.first
    else
     nil
    end
  end

And this is the AppHelper method

def current_profile
  unless @current_profile.nil?
    @current_profile
  end
end

Any idea?

Upvotes: 0

Views: 230

Answers (3)

fixr
fixr

Reputation: 11

Create a lib (for organization purposes) that extends ActionController::Base and define "set_profile" and "current_profile" there as a helper method, then require it and call it on ApplicationController.

application_controller.rb

require 'auth'

before_filter :set_profile # sets the profile on every request, if any

lib/auth.rb

class ActionController::Base
  helper_method :set_profile, :current_profile

  protected

  def set_profile
    if params[:username]
      session[:user_profile] = params[:username]
      ...
    end
  end

  def current_profile
    @current_profile ||= if session[:user_profile]
      ...
    else
      ...
    end
  end

end

That way you can call current_profile anywhere in your code (view and controllers).

Upvotes: 1

Dfr
Dfr

Reputation: 4185

@current_profile as memeber variable of ApplicationController is not visible in your helper. You should create accessor method in Appcontroller like:

def current_profile
  @current_profile
end

or via

attr_accessor :current_profile

And in helper (make sure that accessor in controller is not private):

def current_profile
  controller.current_profile
end

But you also free to define this as helper only, without involving controller at all:

  def current_profile
    if params[:username]
      @current_profile ||= Profile.where(username: params[:username]).first
    end
  end

This will automagically cache you database query in @current_profile and automagically return nil if there is no param specified. So no need for extra else clause and extra set_... method

Upvotes: 0

ichigolas
ichigolas

Reputation: 7725

If you have a relation where User has_many :profiles you can add a current:boolean column on profiles. Then:

def set_profile
  if params[:profile_id]
    @current_profile = Profile.find(params[:profile_id])
    @current_profile.current = true
  else
    nil
  end
end

# helper_method
def current_profile
   @current_profile
end

Upvotes: 0

Related Questions