Search code examples
ruby-on-railssqlitepostgresqlruby-on-rails-3.1heroku

Heroku deployment of Ruby on Rails Application with custom functions


I have designed a ruby on rails 3.2 application in which I have a Users model. I wrote a custom function in order to authenticate userName and password through another mobile application. Everything is working fine in localhost and I am able to authenticate from the mobile application. So, I went a step further and deployed it in Heroku. Now the authenticate function is not working.

In my Gem File I have included the following:

group :production do
  gem 'pg'
end

group :development do
  gem 'sqlite3'
end

In my users_controller.rb I have written my custom authenticate function:

  # http://wgo-ror.herokuapp.com/users/authenticate?userName=ramy&password=123456
  def authenticate     
     usr = params[:userName]
     pwd = params[:password]
     @getUser = User.where("userName = ? AND password = ?", params[:userName], params[:password])     
     if (@getUser!=[])       
       respond_to do |format| 
        format.html { render :json => {:Success => true, :Data => @getUser}, :callback => params[:callback] }
        format.json { render :json => {:Success => true, :Data => @getUser}, :callback => params[:callback] }
       end
     else           
      respond_to do |format|
        format.html { render :json => {:Success => false, :Data => @getUser}, :callback => params[:callback] }
        format.json { render :json => {:Success => false, :Data => @getUser}, :callback => params[:callback] }
      end 
     end
  end

I have also written another custom function called saveUser. This particular function is working fine even after I deployed it to heroku.

  # http://wgo-ror.herokuapp.com/users/saveUser?id=1&userName=yrkapil&password=123456&[email protected]  
  def saveUser
     @user = User.find(params[:id])              
     @user.update_attributes(:userName => params[:userName], :password => params[:password], :email => params[:email] )
  end

In my routes.rb I have included the following:

  match 'users/authenticate' => 'users#authenticate', :as => :authenticate
  match 'users/saveUser' => 'users#saveUser', :as => :saveUser

  resources :users

  resources :festivals

  root :to => 'users#index'

Am I missing something or is it because of postgresql? I am not getting any clue of how to do it. Please help me Guys. I really need to get this working. Thanks in advance!


Solution

  • You probably have a case issue in your userName column.

    You created your userName column with something like this:

    t.string :userName
    

    and that would cause Rails to send SQL like this to the database:

    create table users (
        "userName" varchar(255),
        ...
    )
    

    Note the quotes around the userName identifier; the quotes make that column name case sensitive. But, unquoted identifiers in PostgreSQL are folded to lower case (the SQL standard says upper case but that's immaterial here). Essentially the quotes mean that you always have to say "userName" when referring to the column, you can't say username or userName or anything else.

    SQLite, on the other hand, has a very loose interpretation of SQL so you can do things like this:

    create table t ("userName" text);
    insert into t values ('x');
    select * from t where username = 'x';
    

    and everything will work.

    Every time you let ActiveRecord build the column name, it will quote it so this:

     @user.update_attributes(:userName => params[:userName], :password => params[:password], :email => params[:email] )
    

    will end up doing this:

    update users
    set "userName" = ...
    

    and everyone is happy. However, you are using an SQL fragment right here:

    @getUser = User.where("userName = ? AND password = ?", params[:userName], params[:password])
    

    without quoting your userName identifier so PostgreSQL is probably complaining about an unknown column. If you did this:

    @getUser = User.where('"userName" = ? AND password = ?', params[:userName], params[:password])
    

    you'd have better luck. Or you could do this:

    @getUser = User.where(:userName => params[:userName], :password => params[:password])
    

    or this:

    @getUser = User.where(:userName => params[:userName]).where(:password => params[:password])
    

    You should do two things:

    1. Stop using mixed case column names. Lower case column and table names with underscores to separate words is the usual practice with PostgreSQL (and Ruby and Rails for that matter).
    2. Stop developing on top of SQLite and start developing on top of PostgreSQL if you're deploying to Heroku. Your development stack and your deployment stack should be the same (or as close to identical as possible).