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?
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. :)