Commit affc9921

mo khan <mo@mokhan.ca>
2014-06-01 20:32:48
extract latitude and longitude from image.
1 parent 84f3923
Changed files (7)
app
services
application
db
spec
fixtures
images
services
application
app/services/application/handlers/process_photo.rb
@@ -8,11 +8,20 @@ class ProcessPhoto
   end
 
   def handle(message)
+    file = File.open(message[:file_path])
     photo = @photos.find(message[:photo_id])
-    photo.image = File.open(message[:file_path])
+    photo.image = file
     photo.image_processing = false
     photo.content_type = message[:content_type]
     photo.original_filename = message[:original_filename]
+    photo.latitude, photo.longitude = parse_exif_from(file)
     photo.save!
   end
+
+  private
+
+  def parse_exif_from(file)
+    exif = EXIFR::JPEG.new(file)
+    [exif.gps.latitude, exif.gps.longitude]
+  end
 end
db/migrate/20140601195859_add_geolocation_to_photos.rb
@@ -0,0 +1,6 @@
+class AddGeolocationToPhotos < ActiveRecord::Migration
+  def change
+    add_column :photos, :latitude, :float
+    add_column :photos, :longitude, :float
+  end
+end
db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20140531153240) do
+ActiveRecord::Schema.define(version: 20140601195859) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -30,8 +30,8 @@ ActiveRecord::Schema.define(version: 20140531153240) do
 
   create_table "avatars", force: true do |t|
     t.integer  "user_id"
-    t.datetime "created_at",        null: false
-    t.datetime "updated_at",        null: false
+    t.datetime "created_at"
+    t.datetime "updated_at"
     t.string   "avatar"
     t.boolean  "avatar_processing"
     t.string   "avatar_tmp"
@@ -93,8 +93,8 @@ ActiveRecord::Schema.define(version: 20140531153240) do
     t.datetime "failed_at"
     t.string   "locked_by"
     t.string   "queue"
-    t.datetime "created_at",             null: false
-    t.datetime "updated_at",             null: false
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree
@@ -111,8 +111,13 @@ ActiveRecord::Schema.define(version: 20140531153240) do
 
   create_table "interests", force: true do |t|
     t.string   "name"
-    t.datetime "created_at", null: false
-    t.datetime "updated_at", null: false
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  create_table "page_views", force: true do |t|
+    t.integer "user_id"
+    t.string  "url"
   end
 
   create_table "photos", force: true do |t|
@@ -124,6 +129,8 @@ ActiveRecord::Schema.define(version: 20140531153240) do
     t.boolean  "image_processing"
     t.string   "content_type"
     t.string   "original_filename"
+    t.float    "latitude"
+    t.float    "longitude"
   end
 
   add_index "photos", ["creation_id"], name: "index_photos_on_creation_id", using: :btree
@@ -153,8 +160,8 @@ ActiveRecord::Schema.define(version: 20140531153240) do
     t.text     "description"
     t.string   "url"
     t.integer  "user_id"
-    t.datetime "created_at",  null: false
-    t.datetime "updated_at",  null: false
+    t.datetime "created_at"
+    t.datetime "updated_at"
     t.string   "image_url"
     t.string   "author"
     t.string   "author_url"
@@ -163,12 +170,12 @@ ActiveRecord::Schema.define(version: 20140531153240) do
   add_index "tutorials", ["user_id"], name: "index_tutorials_on_user_id", using: :btree
 
   create_table "users", force: true do |t|
-    t.string   "email",                              default: "", null: false
-    t.string   "encrypted_password",     limit: 128, default: "", null: false
+    t.string   "email",                  default: "", null: false
+    t.string   "encrypted_password",     default: "", null: false
     t.string   "reset_password_token"
     t.datetime "reset_password_sent_at"
     t.datetime "remember_created_at"
-    t.integer  "sign_in_count",                      default: 0
+    t.integer  "sign_in_count",          default: 0
     t.datetime "current_sign_in_at"
     t.datetime "last_sign_in_at"
     t.string   "current_sign_in_ip"
@@ -187,13 +194,13 @@ ActiveRecord::Schema.define(version: 20140531153240) do
     t.datetime "confirmed_at"
     t.datetime "confirmation_sent_at"
     t.string   "unconfirmed_email"
-    t.integer  "failed_attempts",                    default: 0
+    t.integer  "failed_attempts",        default: 0
     t.string   "unlock_token"
     t.datetime "locked_at"
     t.string   "authentication_token"
     t.string   "invitation_token"
     t.string   "full_address"
-    t.integer  "creations_count",                    default: 0
+    t.integer  "creations_count",        default: 0
     t.boolean  "is_admin"
   end
 
spec/fixtures/images/gps.jpg
Binary file
spec/services/application/handlers/process_photo_spec.rb
@@ -11,7 +11,7 @@ describe ProcessPhoto do
   end
 
   describe "#handle" do
-    let(:image_path) { File.join(Rails.root, 'spec/fixtures/images/example.png') }
+    let(:image_path) { File.join(Rails.root, 'spec/fixtures/images/gps.jpg') }
     let(:photo) { Photo.new(id: rand(100), image_processing: true) }
 
     before :each do
@@ -25,7 +25,6 @@ describe ProcessPhoto do
       subject.handle(message)
     end
 
-
     it "saves the uploaded image" do
       photo.image.should_not be_nil
     end
@@ -39,7 +38,16 @@ describe ProcessPhoto do
     end
 
     it "specifies the original filename" do
-      photo.original_filename = 'blah.jpg'
+      photo.original_filename.should == 'blah.jpg'
+    end
+
+    it "applies the geolocation information" do
+      photo.latitude.should == 51.07296369444445
+      photo.longitude.should == -114.101799
+    end
+
+    xit "ignore geolocation for files that dont have geolocation info" do
+      
     end
   end
 end
Gemfile
@@ -33,6 +33,7 @@ gem 'exception_notification'
 gem 'gibbon'
 gem 'twitter'
 gem 'spank'
+gem 'exifr'
 
 group :development do
   gem 'capistrano'
Gemfile.lock
@@ -104,6 +104,7 @@ GEM
       activesupport (>= 3.0.4)
     excon (0.33.0)
     execjs (2.0.2)
+    exifr (1.1.3)
     factory_girl (4.4.0)
       activesupport (>= 3.0.0)
     factory_girl_rails (4.4.1)
@@ -333,6 +334,7 @@ DEPENDENCIES
   dotenv-deployment
   dotenv-rails
   exception_notification
+  exifr
   factory_girl_rails
   fakes-rspec
   ffaker