Access to mixed in method straight after its been mixedin???

Greg Hauptmann wrote:

Can't I access methods directly after they have been mixed in?

In the code below I get an error at the marked location "undefined local variable or method `current_user' for ApplicationController:Class" even though I've already mixed in the variable into the class. Note that when I use "current_user.login" in another place, for example in an action in a specific controller, it works fine, but just not here in the ApplicationController directly after the mix in.

Can you spot why at all? Tks in advance.

============================================
class ApplicationController < ActionController::Base
  include ActiveRbacMixins::ApplicationControllerMixin
  u = current_user.login <=== ERROR OCCURS HERE
end

module ActiveRbacMixins
  module ApplicationControllerMixin
    def self.included(base)
      base.class_eval do
        protected
          def current_user
            return @active_rbac_user unless @active_rbac_user.nil?
            @active_rbac_user =
                    if session[:rbac_user_id].nil? then
                      ::AnonymousUser.instance
                    else
                      ::User.find(session[:rbac_user_id])
                    end
            return @active_rbac_user
          end
      end
    end
  end
end

current_user is an ApplicationController instance method, which
you can't use in the class context of a class definition.
Perhaps you want to put the setting of u (or @u) in a before_filter.

Tks - but I still don’t quite understand then why the following works say however:

PS. just did some more testing and have proved to myself that “current_user” (created by a mixin with the “class_eval” concept) can’t be accessed via a “before_filter”, however and can access it and see it find if I put it within a method. See code snippet below.

Can anyone explain why this occurs? Also how can I get access to this variable in a “before_filter” or directly within the superclass, as I dont’ want to have to try to put the same line of code in all the different actions :frowning:

class ContactsController < ApplicationController
before_filter { Suberb.current_user_gregs = current_user.login } <== “ERROR HERE”

def edit
Suberb.current_user_gregs = current_user.login <== ACTUALLY WORKS HERE ?

end
.
.
.
end

Greg H wrote:

PS. just did some more testing and have proved to myself that "current_user" (created by a mixin with the "class_eval" concept) can't be accessed via a "before_filter", however and can access it and see it find if I put it within a method. See code snippet below.

Can anyone explain why this occurs? Also how can I get access to this variable in a "before_filter" or directly within the superclass, as I dont' want to have to try to put the same line of code in all the different actions :frowning:

class ContactsController < ApplicationController
    before_filter { Suberb.current_user_gregs = current_user.login } <== "ERROR HERE"

If you write a filter as block you have to use a controller parameter
in order to access current controller instance methods.

   before_filter { |c| Suberb.current_user_gregs = c.current_user.login }

  def edit
    Suberb.current_user_gregs = current_user.login <== ACTUALLY WORKS HERE ?
  end

Yes, edit is a controller instance method that has access to
current_user, another controller instance method.

You can now write:

   before_filter :edit

Greg H wrote:

Tks - but I still don't quite understand then why the following works say however:

=====
    include ActiveRbacMixins::ApplicationControllerMixin
    @a = 1
    @b = @a <=== WORKS
    u = current_user.login <=== DOESN'T WORK

You are in a class not an instance context here, so you
can't access the current_user instance method.

Instance variables are normally associated with an
instance of a class object, being initialized in the
class' initialize method. But, as you have done, they can
also be defined in the class context of a class definition.
In this case the variables are like double-@ class variables,
but are local to the class, and not accessible by descendent
classes. e.g:

  class A
           @a = 1
           @@a = 2
           def A.d
             p @a
             p @@a
           end
         end

         class B < A
         end

A.d prints

1
2

While B.d prints

nil
2

I thought conceptually that the "include" along with the mixin'ed method of " base.class_eval do" was effectively injecting "current_user" into the class so that it would be effectively equivalent to the "@a" variable? Like the "@a=1" line seems to get run?

class_eval injects its receiver as self. Here the receiver is base, which
is ApplicationController. Inside the class_eval block the current_user
method has been defined as "def current_user", not "def self.current_user",
so when the module is included current_user becomes an ApplicationController
instance method.

It may have been done for some other reason, but in the way you're
including the module there was no need to define self.included and
use class_eval. All that needed to be done was to def the current_user
method inside the mixin module.

thanks Mark