Search code examples
ruby-on-railspostgresqlherokuomniauthrails-postgresql

OmniAuth ActiveRecord error when pushing to Heroku


I'm having a strange situation occuring where I'm able to read and save information from a Facebook response via Omniauth when running locally, but when I push the exact code to Heroku the error below is coming up (from my logs) regarding the column first_name.

Processing by AdminController#index as HTML
Rendered admin/list_users.html.erb within layouts/application (60.9ms)
Completed 500 Internal Server Error in 163ms

ActionView::Template::Error (undefined method `first_name' for #<Aquarist:0x00000001ee8>):
:       <td>Nickname: <%= aquarist.nickname %>
:     32:           Last: <%= aquarist.last_name %></td>
:     29:       <td><%= aquarist.name %></td>
:     31:           First: <%= aquarist.first_name %>
:     34:       <td><%= aquarist.email %></td>
:     28:       <td><%= image_tag(aquarist.image, :width => '20') %></td>
:     33:       <td><%= aquarist.provider %></td>

I'm using the term "aquarist" in place of user... I know this isn't standard use but for my use case it seems to make a bit more sense. I may change it back in time...

Here's my facebook callback from omniauth:

--- !ruby/hash:OmniAuth::AuthHash
provider: facebook
uid: '12456789'
info: !ruby/hash:OmniAuth::AuthHash::InfoHash
  email: my@email.address.com
  name: Alex
  first_name: Alex
  last_name: Lastname
  image: http://graph.facebook.com/123456789/picture?type=square
  urls: !ruby/hash:Hashie::Mash
    Facebook: http://www.facebook.com/profile.php?id=12456789
credentials: !ruby/hash:Hashie::Mash
  token: AACCCCb1i3ZALXEMfGxJtKZA
  expires_at: 13378794564
  expires: true
extra: !ruby/hash:Hashie::Mash
   raw_info: !ruby/hash:Hashie::Mash
     id: '12456789'
     name: Alex Lastname
     first_name: Alex
     last_name: Lastname
     link: http://www.facebook.com/profile.php?id=12456789
     gender: male
     email: my@email.address.com
     timezone: 11
     locale: en_US
     verified: true
     updated_time: '2012-02-01T12:51:00+0000'

As you can see I've locked down my facebook profile so don't expect to get all the extra information (eg relationship status etc).

I'm trying to build a basic profile of new users ("aquarists" in my terminology) which will pick up some of the extra information they are happy to share from facebook.

When I do this locally it works fine, I can collect my first_name, last_name, gender and locale for instance and save it to the database.

Here's the code I'm using to write the profile

def self.create_with_omniauth(auth)
 create! do |aquarist|
   aquarist.provider        = auth["provider"]
   aquarist.uid             = auth["uid"]
   aquarist.name            = auth["info"]["name"]
   aquarist.nickname        = auth["info"]["nickname"]
   aquarist.email           = auth["info"]["email"]
   aquarist.image           = auth["info"]["image"]
   aquarist.first_name      = auth["extra"]["raw_info"]["first_name"] 
   aquarist.last_name       = auth["extra"]["raw_info"]["last_name"]
   aquarist.user_location   = auth["extra"]["raw_info"]["user_location"]
   aquarist.user_hometown   = auth["extra"]["raw_info"]["user_hometown"]
   aquarist.age             = auth["extra"]["raw_info"]["age"]
   aquarist.locale          = auth["extra"]["raw_info"]["locale"]
   aquarist.gender          = auth["extra"]["raw_info"]["gender"]
 end
end

I'm then using this code to display this profile information (in a table):

<% @aquarists.each do |aquarist|%>
<tr class="tbody">
    <td><%= aquarist.uid %></td>
    <td><%= image_tag(aquarist.image, :width => '20') %></td>
    <td><%= aquarist.first_name %></td>
    ..and so on

The identical information when I push this code comes up with the active record error as per above.

If however I remove any of the columns from the [raw_info][extra] section the code works on Heroku (eg full name, UID, provider etc are all saved to the db).

The thing that has me completely confused is that this code is working locally - so I gather I'm requesting data from the "raw_info" section correctly.

I've already confirmed I've run my migrations on Heroku, and have - as some of other Q&As suggest - also used 'heroku restart' to ensure the database columns are being picked up in the app.

This is my OmniAuth entry in my gemfile:

gem 'omniauth'
gem 'omniauth-twitter'
gem 'omniauth-facebook'

I'm running Rails 3.1.3 and postgres 9.1.2 locally. I'm using the free Heroku database which I believe runs PG 8.x.

Here's an extract from the migration file that creates the particular columns:

def change
  add_column("aquarists", "first_name", :text, :default => "")
  add_column("aquarists", "last_name", :text, :default => "")
  add_column("aquarists", "gender", :text, :default => "")
  add_column("aquarists", "user_location", :text, :default => "")
  add_column("aquarists", "user_relationships", :text, :default => "")
  add_column("aquarists", "user_hometown", :text, :default => "")
  add_column("aquarists", "age", :integer)
  add_column("aquarists", "locale", :text, :default => "")
  add_column("aquarists", "image", :text, :default => "")
  add_column("aquarists", "timezone", :text, :default => "")
  add_column("aquarists", "last_login", :datetime)
end

And this is what comes back when I run heroku console:

$ heroku run console
Running console attached to terminal... up, run.1
Loading production environment (Rails 3.1.3)
irb(main):001:0> Aquarist.new
=> #<Aquarist id: nil, nickname: nil, name: nil, email: nil, created_at: nil, updated_at: nil, provider: nil, uid: nil, admin: false, age: nil, locale: "", image: "", timezone: "", last_login: nil, visits: nil>
irb(main):002:0> 

Any views on what may be happening when my code is hitting Heroku? Is it a Postgres version issue?


Solution

  • Worked out what it was ... a botched migration file. Somewhere along the line I made a (silly) modification to an original migration file, and ran it correctly in my development environment but forgot to reverse the change online.

    Won't do that again, I could do with the 8 or so hours back in my life. :)