aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfrancis <francis>2009-08-05 16:31:10 +0000
committerfrancis <francis>2009-08-05 16:31:10 +0000
commit0610eeb4597138723cce97dcd0c4702a0de0dbcd (patch)
tree73c3c36b700911f41ac5b2be08aee36efd99085b
parent9d3f7b1d205e36768e0910d4748ee913cb8df60f (diff)
Some (as yet unused) profile photo code done on a whim on the train while it
was my birthday.
-rw-r--r--app/controllers/user_controller.rb8
-rw-r--r--app/models/profile_photo.rb88
-rw-r--r--app/models/user.rb13
-rw-r--r--db/migrate/079_add_profile_photo.rb20
-rw-r--r--db/schema.rb8
-rw-r--r--spec/fixtures/parrot.jpgbin0 -> 15232 bytes
-rw-r--r--spec/fixtures/parrot.pngbin0 -> 96431 bytes
-rw-r--r--spec/models/profile_photo_spec.rb40
-rw-r--r--spec/models/user_spec.rb32
-rw-r--r--spec/spec_helper.rb6
10 files changed, 212 insertions, 3 deletions
diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb
index 6d3cb3480..cf1eb1d2c 100644
--- a/app/controllers/user_controller.rb
+++ b/app/controllers/user_controller.rb
@@ -4,7 +4,7 @@
# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved.
# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
#
-# $Id: user_controller.rb,v 1.66 2009-04-23 12:17:06 tony Exp $
+# $Id: user_controller.rb,v 1.67 2009-08-05 16:31:10 francis Exp $
class UserController < ApplicationController
# Show page about a user
@@ -314,4 +314,10 @@ class UserController < ApplicationController
render :action => 'confirm' # must be same as for send_confirmation_mail above to avoid leak of presence of email in db
end
+ def set_profile_photo
+ @photo_user = User.find(params[:id])
+ new_profile_photo = ProfilePhoto.new(:data => data)
+ @photo_user.set_profile_photo(new_profile_photo)
+ end
end
+
diff --git a/app/models/profile_photo.rb b/app/models/profile_photo.rb
new file mode 100644
index 000000000..23c85c133
--- /dev/null
+++ b/app/models/profile_photo.rb
@@ -0,0 +1,88 @@
+# models/profile_photo.rb:
+# Image of user that goes on their profile.
+#
+# Copyright (c) 2009 UK Citizens Online Democracy. All rights reserved.
+# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
+#
+# $Id: profile_photo.rb,v 1.1 2009-08-05 16:31:11 francis Exp $
+#
+require 'mahoro'
+require 'RMagick'
+
+class ProfilePhoto < ActiveRecord::Base
+ WIDTH = 96
+ HEIGHT = 96
+
+ has_one :user
+ validates_presence_of :user
+
+ # deliberately don't strip_attributes, so keeps raw photo properly
+
+ # convert binary data blob into ImageMagick image when assigned
+ attr_accessor :image
+ def data=(data)
+ write_attribute(:data, data)
+ if data.nil?
+ self.image = nil
+ return
+ end
+
+ image_list = Magick::ImageList.new
+ begin
+ image_list.from_blob(data)
+ rescue Magick::ImageMagickError
+ self.image = nil
+ write_attribute(:data, nil)
+ return
+ end
+
+ self.image = image_list[0] # XXX perhaps take largest image or somesuch if there were multiple in the file?
+ self.convert_image
+ end
+
+ # make image valid format and size
+ def convert_image
+ if self.data.nil?
+ return
+ end
+ if self.image.nil?
+ return
+ end
+
+ # convert to PNG if it isn't, and to right size
+ altered = false
+ if self.image.format != 'PNG'
+ self.image.format = 'PNG'
+ altered = true
+ end
+ if image.columns != WIDTH || image.rows != HEIGHT
+ image.resize_to_fill!(WIDTH, HEIGHT)
+ altered = true
+ end
+ if altered
+ write_attribute(:data, self.image.to_blob)
+ end
+ end
+
+ def validate
+ if self.data.nil?
+ errors.add(:data, "^No image specified")
+ return
+ end
+
+ if self.image.nil?
+ errors.add(:data, "^Couldn't read the image that you uploaded, please try again.")
+ return
+ end
+
+ if self.image.format != 'PNG'
+ errors.add(:data, "^Failed to convert image to a PNG")
+ end
+
+ if self.image.columns != WIDTH || self.image.rows != HEIGHT
+ errors.add(:data, "^Failed to convert image to the correct size: at #{self.image.columns}x#{self.image.rows}, need #{WIDTH}x#{HEIGHT}")
+ end
+ end
+end
+
+
diff --git a/app/models/user.rb b/app/models/user.rb
index 4853d633c..7bb5118ac 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -23,7 +23,7 @@
# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved.
# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
#
-# $Id: user.rb,v 1.97 2009-07-03 11:43:37 francis Exp $
+# $Id: user.rb,v 1.98 2009-08-05 16:31:11 francis Exp $
require 'digest/sha1'
@@ -42,6 +42,7 @@ class User < ActiveRecord::Base
has_many :post_redirects
has_many :track_things, :foreign_key => 'tracking_user_id', :order => 'created_at desc'
has_many :comments, :order => 'created_at desc'
+ has_one :profile_photo
attr_accessor :password_confirmation, :no_xapian_reindex
validates_confirmation_of :password, :message =>"^Please enter the same password twice"
@@ -254,6 +255,16 @@ class User < ActiveRecord::Base
return PublicBody.extract_domain_from_email(self.email)
end
+ def set_profile_photo(new_profile_photo)
+ ActiveRecord::Base.transaction do
+ if !self.profile_photo.nil?
+ self.profile_photo.destroy
+ end
+ new_profile_photo.user = self
+ self.profile_photo = new_profile_photo
+ end
+ end
+
private
def self.encrypted_password(password, salt)
diff --git a/db/migrate/079_add_profile_photo.rb b/db/migrate/079_add_profile_photo.rb
new file mode 100644
index 000000000..a6c031d89
--- /dev/null
+++ b/db/migrate/079_add_profile_photo.rb
@@ -0,0 +1,20 @@
+class AddProfilePhoto < ActiveRecord::Migration
+ def self.up
+ create_table :profile_photos do |t|
+ t.column :data, :binary, :null => false
+ t.column :user_id, :integer, :null => false
+ end
+
+ add_column :users, :profile_photo_id, :integer, :null => true
+
+ if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
+ execute "ALTER TABLE profile_photos ADD CONSTRAINT fk_profile_photos_user FOREIGN KEY (user_id) REFERENCES users(id)"
+ execute "ALTER TABLE users ADD CONSTRAINT fk_users_profile_photo FOREIGN KEY (profile_photo_id) REFERENCES profile_photos(id)"
+ end
+ end
+
+ def self.down
+ remove_column :users, :profile_photo_id
+ drop_table :profile_photos
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 7055727eb..78f0ed992 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -9,7 +9,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 78) do
+ActiveRecord::Schema.define(:version => 79) do
create_table "acts_as_xapian_jobs", :force => true do |t|
t.string "model", :null => false
@@ -142,6 +142,11 @@ ActiveRecord::Schema.define(:version => 78) do
add_index "post_redirects", ["token"], :name => "index_post_redirects_on_token"
add_index "post_redirects", ["updated_at"], :name => "index_post_redirects_on_updated_at"
+ create_table "profile_photos", :force => true do |t|
+ t.binary "data", :null => false
+ t.integer "user_id", :null => false
+ end
+
create_table "public_bodies", :force => true do |t|
t.text "name", :null => false
t.text "short_name", :null => false
@@ -236,6 +241,7 @@ ActiveRecord::Schema.define(:version => 78) do
t.datetime "last_daily_track_email", :default => '2000-01-01 00:00:00'
t.string "admin_level", :default => "none", :null => false
t.text "ban_text", :default => "", :null => false
+ t.integer "profile_photo_id"
end
add_index "users", ["url_name"], :name => "index_users_on_url_name", :unique => true
diff --git a/spec/fixtures/parrot.jpg b/spec/fixtures/parrot.jpg
new file mode 100644
index 000000000..22fd8e4de
--- /dev/null
+++ b/spec/fixtures/parrot.jpg
Binary files differ
diff --git a/spec/fixtures/parrot.png b/spec/fixtures/parrot.png
new file mode 100644
index 000000000..77442a3d5
--- /dev/null
+++ b/spec/fixtures/parrot.png
Binary files differ
diff --git a/spec/models/profile_photo_spec.rb b/spec/models/profile_photo_spec.rb
new file mode 100644
index 000000000..5b05c1205
--- /dev/null
+++ b/spec/models/profile_photo_spec.rb
@@ -0,0 +1,40 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe ProfilePhoto, "when constructing a new photo" do
+
+ before do
+ #@request_event = mock_model(InfoRequestEvent, :xapian_mark_needs_index => true)
+ #@request = mock_model(InfoRequest, :info_request_events => [@request_event])
+ #@user = mock_model(User)
+ end
+
+ it 'should take no image as invalid' do
+ profile_photo = ProfilePhoto.new(:data => nil)
+ profile_photo.valid?.should == false
+ end
+
+ it 'should take bad binary data as invalid' do
+ profile_photo = ProfilePhoto.new(:data => 'blahblahblah')
+ profile_photo.valid?.should == false
+ end
+
+ it 'should accept and convert a PNG to right size' do
+ data = load_image_fixture("parrot.png")
+ profile_photo = ProfilePhoto.new(:data => data, :user => mock_model(User, :valid? => true))
+ profile_photo.valid?.should == true
+ profile_photo.image.format.should == 'PNG'
+ profile_photo.image.columns.should == 96
+ profile_photo.image.rows.should == 96
+ end
+
+ it 'should accept and convert a JPEG to right format and size' do
+ data = load_image_fixture("parrot.jpg")
+ profile_photo = ProfilePhoto.new(:data => data, :user => mock_model(User, :valid? => true))
+ profile_photo.valid?.should == true
+ profile_photo.image.format.should == 'PNG'
+ profile_photo.image.columns.should == 96
+ profile_photo.image.rows.should == 96
+ end
+
+end
+
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index db7753469..7de181300 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -216,3 +216,35 @@ describe User, " when making name and email address" do
end
+describe User, " when setting a profile photo" do
+ before do
+ @user = User.new
+ @user.name = "Sensible User"
+ @user.email = "sensible@localhost"
+ @user.password = "sensiblepassword"
+ end
+
+ it "should attach it to the user" do
+ data = load_image_fixture("parrot.png")
+ profile_photo = ProfilePhoto.new(:data => data)
+ @user.set_profile_photo(profile_photo)
+ profile_photo.user.should == @user
+ end
+
+# it "should destroy old photos being replaced" do
+# ProfilePhoto.count.should == 0
+#
+# data_1 = load_image_fixture("parrot.png")
+# profile_photo_1 = ProfilePhoto.new(:data => data_1)
+# data_2 = load_image_fixture("parrot.jpg")
+# profile_photo_2 = ProfilePhoto.new(:data => data_2)
+#
+# @user.set_profile_photo(profile_photo_1)
+# @user.save!
+# ProfilePhoto.count.should == 1
+# @user.set_profile_photo(profile_photo_2)
+# @user.save!
+# ProfilePhoto.count.should == 1
+# end
+end
+
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 6852909a6..2af585d7a 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -31,6 +31,12 @@ def receive_incoming_mail(email_name, email_to, email_from = 'geraldinequango@lo
RequestMailer.receive(content)
end
+def load_image_fixture(image_name)
+ image_name = File.join(Spec::Runner.configuration.fixture_path, image_name)
+ content = File.read(image_name)
+ return content
+end
+
def rebuild_xapian_index
rebuild_name = File.dirname(__FILE__) + '/../script/rebuild-xapian-index'
Kernel.system(rebuild_name) or raise "failed to launch rebuild-xapian-index"