开发者

validate presence of not working in form_for tag

开发者 https://www.devze.com 2022-12-18 00:24 出处:网络
This is my first time doing validation on a rails application.I saw many tutorials which made it seem easy.I don\'t know why I cant get it to work.

This is my first time doing validation on a rails application. I saw many tutorials which made it seem easy. I don't know why I cant get it to work. Below is my setup.

Controller Admin (action = login)

  def login
    session[:user_id] = nil
    if request.post?
      @user = User.authenticate(params[:userId], params[:password])
      if true
        session[:user_id] = @user.user_id
        flash.now[:notice] = "Login Successful"
        redirect_to(:controller => "pages", :action => "mainpage")
      else
        flash.now[:notice] = "Invalid user/password combination"
      end
    end
  end

So first time user comes to admin/login they are just presented with a form below

login.erb.html

<% form_for :user do |f| %>
  <p><label for="name">User ID:</label> 
    <%= f.text_field :userid %>
  </p>
  <p><label for="password">Password:</label>
    <%= f.password_field :password%>
  </p>
  <p style="padding-left:100px">
    <%= submit_tag 'Login' %>
  </p>
<% end %>

My User model:

class User < ActiveRecord::Base
  validates_presence_of :userid, :password
  de开发者_如何学Cf self.authenticate(userid, password)
    user = self.find_by_userid_and_password(userid, password)
    user
  end
end

Actual field names for userId and password in my DB: userid password

I am expecting behavior that when user does not enter anything in the fields and just clicks submit. it will tell them that userid and password are required fields. However, this is not happening

From the console I can see the messages:

>> @user = User.new(:userid => "", :password => "dsf")
=> #<User id: nil, userid: "", password: "dsf", created_at: nil, updated_at: nil>
>> @user.save
=> false
>> @user.errors.full_messages
=> ["Userid can't be blank"]

So error is somewhere in my form submit...

UPDATE: validations only happen when u SAVE the object....here I am not saving anything. So in this case I have to do javascript validations?


It's the if true line. Change it to

if @user = User.authenticate(params[:userId], params[:password])

or

@user = User.authenticate(params[:userId], params[:password])
if @user
  ...
end

I'd also add redirect_to login_path to the failure case.

You can also slim down your auth method:

def self.authenticate(userid, password)
  find_by_userid_and_password(userid, password)
end


It turns out, there are several issues here, and I'll try to cover them all. Let's start with your model:

class User < ActiveRecord::Base
  validates_presence_of :userid, :password

  def self.authenticate(userid, password)
    self.find_by_userid_and_password(userid, password)
  end
end

The validation doesn't come into play for logging in, only for creating and updating user records. The authentication has been trimmed, because ruby automatically returns the last calculated value in a method.

Next, the login action of your controller:

def login
  session[:user_id] = nil
  if request.post?
    if @user = User.authenticate(params[:userId], params[:password])
      session[:user_id] = @user.user_id
      flash[:notice] = "Login Successful"
      redirect_to(:controller => "pages", :action => "mainpage")
    else
      flash.now[:error] = "Invalid user/password combination"
    end
  end
end

Notice we don't use flash.now on a redirect - flash.now is only if you're NOT redirecting, to keep rails from showing the message twice.

Finally, you shouldn't be using form_for, because this is not a restful resource form. You're not creating or editing a user, so use form_tag instead:

<% form_tag url_for(:controller => :users, :action => :login), :method => :post do %>
  <%= content_tag(:p, flash[:error]) if flash[:error] %>

  <p><label for="name">User ID:</label> 
    <%= text_field_tag :userid %>
  </p>
  <p><label for="password">Password:</label>
    <%= password_field_tag :password%>
  </p>
  <p style="padding-left:100px">
    <%= submit_tag 'Login' %>
  </p>
<% end %>

This will do what you want. This is a great learning exercise, but if you're serious about user authentication in a production application, checkout rails plugins like restful_authentication or clearance that do this for you in a much more sophisticated (and RESTful) way.

0

精彩评论

暂无评论...
验证码 换一张
取 消