Forum: Ruby on Rails Help with authlogin gem

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
171ea139761951336b844e708d1547ab?d=identicon&s=25 James Byrne (byrnejb)
on 2008-12-23 17:57
I am puzzled over how to normalize the login value provided by the user
to  authlogic to validate the existence of that user.  I have threaded
my way through the code and tried to understand what it and the examples
are trying to tell me but I am just not making the connections.

Basically I have this in the login (user_sessions_controller):

  def new
    @user_session = UserSession.new
  end

  def create
    @user_session = UserSession.new(params[:user_session])
    # debugger if ENV['RAILS_ENV'] == 'development'
    @user_session.save do |result|
      if result
        flash[:notice] = "Welcome"
        redirect_back_or_default account_url
      else
        render :action => :new
      end
    end
  end

What I want to do is modify the input value of the login identity field
before the User.find is performed.  It seems that this should be
possible in the User model.

Inside authlogic/session.config.rb I find this:

        # Authlogic tries to validate the credentials passed to it. One
part
        # of validation is actually finding the user and making sure it
        # exists. What method it uses the do this is up to you.
        #
        # Let's say you have a UserSession that is authenticating a
User.
        # By default UserSession will call User.find_by_login(login).
You
        # can change what method UserSession calls by specifying it
here. Then
        # in your User model you can make that method do anything you
want,
        # giving you complete control of how users are found by the
UserSession.
        #
        # Let's take an example: You want to allow users to login by
username
        # or email. Set this to the name of the class method that does
this in
        # the User model. Let's call it "find_by_username_or_email"
        #
        #   class User < ActiveRecord::Base
        #     def self.find_by_username_or_email(login)
        #       find_by_username(login) || find_by_email(login)
        #     end
        #   end
        #
        # * <tt>Default:</tt> "find_by_#{login_field}"
        # * <tt>Accepts:</tt> Symbol or String
        def find_by_login_method(value = nil)
          if value.nil?
            read_inheritable_attribute(:find_by_login_method) ||
              find_by_login_method("find_by_#{login_field}")
          else
            write_inheritable_attribute(:find_by_login_method, value)
          end
        end
        alias_method :find_by_login_method=, :find_by_login_method


This probably tells me exactly what I have to do but I am afraid I
cannot see what that is.  I tried overriding find_by_username but doing
so causes a nil object exception.

class User < ActiveRecord::Base
  acts_as_authentic

  def self.find_by_username(login)
    super.find_by_username(login.strip.squeeze(" ").mb_chars.downcase)
  end

end

NoMethodError (You have a nil object when you didn't expect it!
The error occurred while evaluating nil.find_by_username):
    /app/models/user.rb:29:in `find_by_username'
    /usr/lib/ruby/gems/1.8/gems/authlogic-1.3.7/lib/authlogic/session/base.rb:397:in
`send'

If I do this instead:

  def find_by_username(login)
    self.find_by_username(login.strip.squeeze(" ").mb_chars.downcase)
  end

OR

  def find_by_username(login)
    super.find_by_username(login.strip.squeeze(" ").mb_chars.downcase)
  end

Then the SELECT uses the unmodified value input for the username.

Can anyone provide me with some guidance on how to get this to work as I
desire?

Regards,
171ea139761951336b844e708d1547ab?d=identicon&s=25 James Byrne (byrnejb)
on 2008-12-23 22:29
James Byrne wrote:
> I am puzzled over how to normalize the login value provided by the user
> to  authlogic to validate the existence of that user.  I have threaded
> my way through the code and tried to understand what it and the examples
> are trying to tell me but I am just not making the connections.

This seems to be the place where the problem lies:

[150, 159] in
/usr/lib/ruby/gems/1.8/gems/authlogic-1.3.7/lib/authlogic/session/base.rb
   150        def credentials=(values)
   151          return if values.blank? || !values.is_a?(Hash)
   152          values.symbolize_keys!
   153          values.each do |field, value|
   154            next if value.blank?
=> 155            send("#{field}=", value)
   156          end
   157        end
   158
   159        # Resets everything, your errors, record, cookies, and
session. Basically "logs out" a user.
/usr/lib/ruby/gems/1.8/gems/authlogic-1.3.7/lib/authlogic/session/base.rb:155
send("#{field}=", value)
(rdb:6) v l
  field => "username"
  value => "MYUSER"
  values => {"username"=>"MYUSER", "password"=>"mypassword",
"remember_me"=>"0"}

   361
   362              attr_reader :#{login_field}
   363
=> 364              def #{login_field}=(value)
   365                self.authenticating_with = :password
   366                @#{login_field} = value
   367              end
   368
/usr/lib/ruby/gems/1.8/gems/authlogic-1.3.7/lib/authlogic/session/base.rb:364
def #{login_field}=(value)
(rdb:6) v l
  value => "MYUSER"

When the Session::Base code hits line 366 then the direct assignment of
the @params value of the login_field to the corresponding instance value
simply bypasses the setter defined in the User model, does it not?

Given this construction I cannot see a way to invoke the model's setter
method for the login field.  Am I missing something?
This topic is locked and can not be replied to.