SitePoint Sponsor

User Tag List

Results 1 to 15 of 15
  1. #1
    SitePoint Guru CompiledMonkey's Avatar
    Join Date
    Sep 2002
    Location
    Richmond, VA
    Posts
    975
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Rails and MVC - Some design considerations...

    So I began some work today on a rails application. I used migration and scaffold to build 2 entities: user and task. I see how using the rails tools can get you up and running with CRUD functionality very quickly. I kind of hit a bump when I wanted to do something a little outside of that approach.

    What I want is a login page for my application. Instead of using scaffold I just created a controller (login) and a single view (index). I didn't create a model because the user object I created before is essentially the model. Does this sound right?

    Where can I find some useful information on creating HTML forms with rails? As you can imagine, I need to POST my index view to the login controller and test for values using the user model I had previously created.

    Can anyone help me verify what I've done is right, and possibly help me find some good HTML/form/rails samples on the web?

  2. #2
    SitePoint Addict
    Join Date
    Jan 2006
    Posts
    268
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    There are a number of form helpers included in rails
    http://api.rubyonrails.com/classes/A...ormHelper.html

    In your controller you would do something like

    Code:
      def login
        if request.post?
          user = User.new(params[:user])
          if user.try_to_login
            cookie[:user_id] = user.username
            redirect_to(:controller=>"user", :action => "account")
          else
             flash[:notice] = "Could not log you in"
          end   
        end
      end
    Then in your User model:
    Code:
      def try_to_login
        find(:first, :conditions => [ "username = ? and password = ?", user.username, user.password])
      end
    Basically try_to_login will either return a user object or nil.
    If it returns nil, they will be shown an error, otherwise they will have a cookie set, and be redirected to the appropriate page.

    Now, I wouldn't necessarily suggest using the above code as it would mean that anyone could get into the secure area by making a cookie with someone elses username in it. Also, you would be storing passwords in cleartext in the database. But the idea is there.
    If you give someone a program,
    you will frustrate them for a day;
    if you teach them how to program,
    you will frustrate them for a lifetime.

  3. #3
    SitePoint Guru CompiledMonkey's Avatar
    Join Date
    Sep 2002
    Location
    Richmond, VA
    Posts
    975
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah, that's basically what I was thinking. I'm assuming sessions are just as easy to implement and work with??

  4. #4
    SitePoint Addict
    Join Date
    Jan 2006
    Posts
    268
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    yep, just use session[:what_ever]
    If you give someone a program,
    you will frustrate them for a day;
    if you teach them how to program,
    you will frustrate them for a lifetime.

  5. #5
    SitePoint Guru CompiledMonkey's Avatar
    Join Date
    Sep 2002
    Location
    Richmond, VA
    Posts
    975
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm having some issues getting this to work. Let me post this code and tell me what you see.

    My error is on line 12 of the user.rb class. Which happens to be the find() method. It's saying the user reference is nil. Which makes sense to me, I'm just not sure what to use in Ruby. I would expect to use "this" like in .NET but that doesn't work either. I did a lot of searching last night which is why I have those userA/password methods. At first I didn't have those so I was wondering if I needed get/set methods for any attributes in the class, or if Rails knew about those from the database.

    LoginController.rb
    Code:
      class LoginController < ApplicationController
      
        def index
      	
        end
        
        def authenticate
      	user = User.new()
      	user.userA = params[:userName]
      	user.password = params[:password]
      	
      	if user.authenticate()
      	  redirect_to(:action => "index")
      	else
      	  redirect_to(:controller => "tasks", :action => "list")
      	end
      	
        end
      end

    user.rb - model
    Code:
      class User < ActiveRecord::Base
        
        def userA=(newUserA)
      	@userA = newUserA
        end
        
        def password=(newPassword)
      	@password = newPassword
        end
      
        def authenticate()
      	find(:first, :conditions => [ "user = ? AND password = ?", user.userA, user.password])
        end
      
      end
    login/index - view
    Code:
      <div id="page">
      	Login stuff!<br /><br />
      	
      	<%= start_form_tag :action => 'authenticate' %>
      	  <p>
      		User <%= text_field 'user', 'userName', :size => 25 %>
      		Password <%= text_field 'user', 'password', :size => 25 %>
      	  </p>
      	  <%= submit_tag 'Login!' %>
      	<%= end_form_tag %>
      	
      </div>

  6. #6
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    I typically use the acts_as_authenticated plugin for user logins/sessions.
    Code:
    ./script/plugin install acts_as_authenticated
    Sets up the user table and login/registration sequences for you.

    But to fix your particular issue:
    Code:
    class User < ActiveRecord::Base
        
        def userA=(newUserA)
      	@userA = newUserA
        end
        
        def password=(newPassword)
      	@password = newPassword
        end
      
        def authenticate()
      	find(:first, :conditions => [ "user = ? AND password = ?", @userA, @password])
        end
      
      end
    Or just make User.authenticate available, so you don't have to make a user object:
    Code:
    class User < ActiveRecord::Base
        
        #...
      
        def self.authenticate(username, password)
      	find(:first, :conditions => [ "user = ? AND password = ?", username, password])
        end
      
      end
    
    class LoginController < ApplicationController
      
        def index
      	
        end
        
        def authenticate
          user = User.authenticate(params[:userName], params[:password])
          if user.nil?
            redirect_to :action => 'index'
          else
            redirect_to :controller => 'tasks', :action => 'list'
          end
      	  	
        end
      end

  7. #7
    SitePoint Guru CompiledMonkey's Avatar
    Join Date
    Sep 2002
    Location
    Richmond, VA
    Posts
    975
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I must have a logic error somewhere, because it always redirects back to the index action. It seems to always come back as nil.

  8. #8
    SitePoint Guru CompiledMonkey's Avatar
    Join Date
    Sep 2002
    Location
    Richmond, VA
    Posts
    975
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I've been spinning my wheels on this for awhile and just can't figure out where my problem is. I have a table (users) with id, user, password, firstName, lastName as columns. I have a single record in that table.

    Next, I followed the example you guys posted above. And no matter what I do, I always get redirected to the ":action => 'index'" part. I've tried an invalid user and a valid user. No matter what, always redirected there. Maybe there's a problem with my nil check, or how the parameters are passed in. Any help is greatly appreciated!

    login_controller.rb
    Code:
     class LoginController < ApplicationController
     
       def index
     	
       end
       
       def authenticate
     	user = User.authenticate(params[:userName], params[:password])
     	
     	if user.nil?
     	  redirect_to :action => "index"
     	else
     	  redirect_to :controller => "tasks", :action => "list"
     	end
     	
       end
     end
    user.rb
    Code:
     class User < ActiveRecord::Base
       
       def userA=(newUserA)
     	@userA = newUserA
       end
       
       def password=(newPassword)
     	@password = newPassword
       end
     
       def self.authenticate(userName, password)
     	find(:first, :conditions => [ "user = ? AND password = ?", userName, password])
       end
     
     end
    views/login/index
    Code:
     <div id="page">
     	Login stuff!<br /><br />
     	
     	<%= start_form_tag :action => 'authenticate' %>
     	  <p>
     		User <%= text_field 'user', 'userName', :size => 25 %>
     		Password <%= text_field 'user', 'password', :size => 25 %>
     	  </p>
     	  <%= submit_tag 'Login!' %>
     	<%= end_form_tag %>
     	
     </div>

  9. #9
    SitePoint Addict
    Join Date
    Jan 2006
    Posts
    268
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you look at the output html in your view (View Source.. in the browser)
    you will see that the name of the text fields are
    user[userName] and user[password]
    basically creating a user[] array
    this array is then passed through the params[] array

    so, to access the user array it would be params[:user].
    To access specific data in the user array, it would be params[:user][:field]

    So you can change
    user = User.authenticate(params[:userName], params[:password])

    to
    uses = User.authenticate(parmas[:user][:userName], parmas[:user][:password])

    and that should fix your problem.
    If you give someone a program,
    you will frustrate them for a day;
    if you teach them how to program,
    you will frustrate them for a lifetime.

  10. #10
    SitePoint Guru CompiledMonkey's Avatar
    Join Date
    Sep 2002
    Location
    Richmond, VA
    Posts
    975
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well geez, that makes sense. I'll give that a whirl tonight, thank you.

    If I changed the text box to only have 'userName' and 'password', could I access the parameter array like I'm doing in the controller?

  11. #11
    SitePoint Addict
    Join Date
    Jan 2006
    Posts
    268
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can't use the text_field method and just pass it 'username' because it expects to get 2 paramaters (model, and field) and you'll get an error

    but if you simply wrote it out in html
    Code:
      <input type="text" name="username" />
    Then, yes, you can access it using params[:username]
    If you give someone a program,
    you will frustrate them for a day;
    if you teach them how to program,
    you will frustrate them for a lifetime.

  12. #12
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by pjleonhardt
    You can't use the text_field method and just pass it 'username' because it expects to get 2 paramaters (model, and field) and you'll get an error

    but if you simply wrote it out in html
    Code:
      <input type="text" name="username" />
    Then, yes, you can access it using params[:username]
    Code:
    <%= text_field_tag "username" %>
    _tag makes all the difference

  13. #13
    SitePoint Addict
    Join Date
    Jan 2006
    Posts
    268
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    heh, good call.
    If you give someone a program,
    you will frustrate them for a day;
    if you teach them how to program,
    you will frustrate them for a lifetime.

  14. #14
    SitePoint Guru CompiledMonkey's Avatar
    Join Date
    Sep 2002
    Location
    Richmond, VA
    Posts
    975
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Awesome guys, thanks! I think I'll be asking lots of questions here!

  15. #15
    SitePoint Addict
    Join Date
    Jan 2006
    Posts
    268
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My pleasure, I'm learning rails at the moment too and learn something new almost every day about both the framework on ruby itself. It feels good to be able to help people with the same things I was struggling with a month or 2 ago. The guys at railsforum.com are a wonderful help as well (and usually faster with responses).
    If you give someone a program,
    you will frustrate them for a day;
    if you teach them how to program,
    you will frustrate them for a lifetime.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •