> That's one common way of doing it.

Yet, it worked. Basically, visitor makes a request URL, which Rails 
translates into a controller/action sequence. In order to determine fate 
of URL request, we create a rule that matches the URL path of the 
request and determine where to direct that request. It maps requests to 
action methods inside the controllers. The mapper method parses the 
query string as a hash. So when login is part of query string action 
based on user clicking link, a URL request is made, the mapper method in 
turn is called, and points the request to the login method of the users 
class:

  map.login "login", :controller => "users", :action => "login"

Since we are using named routing, Rails builds a helper method:


  <%= link_to "login", login_path %>

login method is called of UsersController class:

def login
    @user = User.new
    if request.post?
      if session[:user] = User.authenticate(params[:user][:login], 
params[:user][:password])
        flash[:message]  = "Login successful"
        redirect_to :root
      else
        flash[:warning] = "Username or password does not exist"
      end
    end

  end

We instantiate User class and assign the new instance to  instance 
variable @user. Hence, we have a @user object and since during 
instantiation, our new instance inherits from ActiveRecord, the "blank" 
instance in reality inherits getter setter methods translated from users 
table in database. Hence, we accept parameters in the query string that 
will translate to the data we need (e.g. login and password). Since the 
instance variable inherits from ActiveRecord, it has access to some of 
the built in rails helper methods like label, text_field, 
password_field, submit:

<% content_for :login do %>
   <% form_for @user, :url => { :action => "login" } do |f|  %>
    <%= error_messages_for 'user' %><br/>
    <%= f.label(:user_login, "Username")%>
     <%= f.text_field(:login) %><br/>
     <%= f.label(:user_password, "User Password")%>
    <%= f.password_field(:password) %><br/>
    <%= f.submit("Login") %>

    <%= link_to 'Register', :action => 'signup' %> |
      <%= link_to 'Forgot my password', :action => 'forgot_password' %>
  <% end %>
 <% end %>

The helper methods render html output. User inserts value and gets 
converted to a hash with key/value pairs corresponding to field in table 
to its value. Hence, we do the following in controller:

    if request.post?
      if session[:user] = User.authenticate(params[:user][:login], 
params[:user][:password])

When the form is submitted a POST HTTP request is made, and we call the 
class method authenticate on the User class object. We pass in the 
relevant query string information using the params hash.

The authenticate method in turn is called:

  def self.authenticate(login, pass)
       u=find(:first, :conditions=>["login = ?", login])
       return nil if u.nil?
       return u if User.encrypt(pass, u.salt)==u.hashed_password
       nil
     end

We use special syntax self to indicate this is a class method and not an 
instance method and therefore can only be called on the class itself. We 
pass our query string arguments into the authenticate argument 
definition as parameters (local variables) login and pass. We perform a 
sql query to our mysql database, searching first record of login field 
that matches value passed. We assign result to local variabnle u. If u 
is nil, we return nil, and the if statement's argument will be converted 
to BOOLEAN false (which I believe is object not a primitive in ruby?):

if session[:user] = User.authenticate(params[:user][:login], 
params[:user][:password])

Hence, else statement is invoked:

        flash[:warning] = "Username or password does not exist"

Otherwise, we return u (the data set of current user):

       return u if User.encrypt(pass, u.salt)==u.hashed_password

We do this if the encrupt method returns a value equal to what the 
hashed_password method's value is.

So returning u will convert the if booleon to true and if statement 
returns immediate block:

        flash[:message]  = "Login successful"
        redirect_to :root

The user is logged in successful.

One thing I forgot to mention is we assign the local variable u to the 
session :user:

      if session[:user] = User.authenticate(params[:user][:login], 
params[:user][:password])

Hence, the session has this user stored.

THis is a little unclear to me though:
 session[:user]

We are storing a symbol called :user in sesion associative array. So 
:user is initiaized with vaue of u (whcih is dataset we returned). 
What's the purpose of using symbol here? Why can't we use something else 
like a variable?

THanks for response.

-- 
Posted via http://www.ruby-forum.com/.

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to