alexeim
alexeim

Reputation: 7

activerecord exists always return false

I'm checking if a record exists in my database, but it keeps returning false even when it does exist. I tried in rails's console aswell it returns true, but in my app it doesn't work i can't seem to find why ? Update (full code):

class FormulaireController < ApplicationController
  def index
    @accounts = Account.all
    @account = session[:logged] ? Account.find_by(username: session[:username]) : Account.new
  end

  def create
    if params[:loginbtn]
      if Account.exists?(account_params)
        @account            = Account.find_by(username: params[:username])
        session[:username]  = @account.username
        session[:logged]    = true
        redirect_to root_path, notice: "Hello, #{@account.username}! You successfully logged in!" and return
      else
        redirect_to root_path, notice: "Invalid username or password. Create a new account ?" and return
      end
    else
      @account = Account.new(account_params)
      if Account.exists?(:username => @account.username)
        redirect_to root_path, notice: "Username already taken !" and return
      elsif @account.save
        session[:username]  = @account.username
        session[:logged]    = true
        redirect_to root_path, notice: "Hello, #{@account.username}! You successfully created your account!" and return
      end
    end
    render 'index'
  end

  def logout
    if session[:logged]
      reset_session
      redirect_to root_path, notice: "Successfully logged out !" and return
    end
    render 'index'
  end

  private
    def account_params
      params.require(:account).permit(:username, :password)
    end
end

i know this is not secure at all, but this is just to learn rails i am a beginner.

heres my form:

<%= form_for @account, url: create_path, method: :post do |f| %>
    <div class="input-group col-xs-6">
      <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
      <%= f.text_field :username, class: "form-control" %>
    </div><br>
    <div class="input-group col-xs-6">
      <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
      <%= f.password_field :password, class: "form-control" %>
    </div><br>
    <div class="form-group">
      <% if session[:logged] %>
        <%= link_to "Disconnect", logout_path, class: "btn btn-primary" %>
      <% else %>
        <%= f.submit "Login", name: "loginbtn", class: "btn btn-primary" %>
      <% end %>
      <%= f.submit "Register", name: "registerbtn", class: "btn btn-success" %>
    </div>
  <% end %>

routes.rb:

  Rails.application.routes.draw do

   root  :to        => 'formulaire#index'
   get   '/logout'  => 'formulaire#logout'
   post  '/create'  => 'formulaire#create'

  end

i checked manually for params and it returns the correct value, i also check my DB it's correct, but it keeps returning false when i use exists? method

Update (console log):

    Started POST "/create" for 127.0.0.1 at 2017-06-29 19:29:27 +0200
    Processing by FormulaireController#create as HTML
      Parameters: {"utf8"=>"✓", "authenticity_token"=>"ttElLyvYuuGY1noKEfT7Vqg7HY2sFJehi/ZgESRftjwbBzVQVS7uOKvEADbYiCuw9xJNIZGICrM36c9x2hWKCQ==", "account"=>{"username"=>"Henrygolant", "password"=>"[FILTERED]"}, "loginbtn"=>"Login"}
      Account Load (0.2ms)  SELECT  `accounts`.* FROM `accounts` WHERE `accounts`.`username` IS NULL LIMIT 1
    Redirected to http://localhost:3000/
    Completed 302 Found in 2ms (ActiveRecord: 0.2ms)

Started GET "/" for 127.0.0.1 at 2017-06-29 19:29:27 +0200
Processing by FormulaireController#index as HTML
  Rendering formulaire/index.html.erb within layouts/application
  Account Exists (0.2ms)  SELECT  1 AS one FROM `accounts` LIMIT 1
  Account Load (0.2ms)  SELECT `accounts`.* FROM `accounts`
  Rendered formulaire/index.html.erb within layouts/application (2.9ms)
Completed 200 OK in 28ms (Views: 26.7ms | ActiveRecord: 0.3ms)

Upvotes: 0

Views: 881

Answers (2)

jvillian
jvillian

Reputation: 20263

You should do it more like this:

def create
  if params[:loginbtn]
    if @account = Account.find_by(username: params[:account][:username])
      session[:username]  = @account.username
      session[:logged]    = true
      redirect_to root_path, notice: "Hello, #{@account.username}! You successfully logged in!" and return
    else
      redirect_to root_path, notice: "Invalid username or password. Create a new account ?" and return
    end
  else
    @account = Account.new(account_params)
    if @account.save?
      session[:username]  = @account.username
      session[:logged]    = true
      redirect_to root_path, notice: "Hello, #{@account.username}! You successfully created your account!" and return
    else
      redirect_to root_path, notice: "Username already taken !" and return
    end
  end
  render 'index'  
end

In the case of login, if @account is nil (i.e., is not found/doesn't exist), then you'll fall through to your else statement.

In the case of register, if @account.save fails (i.e., is not valid because user name is already taken), then you also fall through to your else statement.

Also, I'm not sure you need:

elsif params[:registerbtn]

Unless there's some other way to submit the form. So maybe just else.

Pavan's suggestion is a good one. In which case, this could become:

def create
  if @account = Account.find_or_create_by(account_params)
    session[:username]  = @account.username
    session[:logged]    = true
    redirect_to root_path, notice: "Hello, #{@account.username}! You successfully logged in!" and return
  else
    redirect_to root_path, notice: "Invalid username or password. Create a new account ?" and return
  end
  render 'index'  
end

Upvotes: 0

Pavan
Pavan

Reputation: 33542

I checked manually for params and it returns the correct value, i also check my DB it's correct, but it keeps returning false when i use exists? method

The exists? method expects either Integer/String/Array/Hash as a argument, but you are passing account_params which is an instance of ActionController::Parameters. So it always returns false.

It seems like find_or_create_by could be a best fit for what you are trying to do

Upvotes: 2

Related Questions