added collections. rewrote some code

This commit is contained in:
Espen Antonsen 2009-06-03 01:33:39 +02:00
parent f2599d9f46
commit 1ae1716a0b
31 changed files with 315 additions and 87 deletions

4
README
View file

@ -4,8 +4,10 @@ Made by Espen Antonsen
== Requirements == Requirements
Tested with Ruby 1.8.6 and Rails 2.3
Software Software
- FreeIamge (required for Image Science) - FreeImage (required for Image_Science)
- ExifTool (required for Mini_EfixTool) - ExifTool (required for Mini_EfixTool)
Ruby Gems Ruby Gems

View file

@ -10,6 +10,15 @@ class AlbumsController < ApplicationController
end end
end end
def untouched
@albums = Album.untouched()
respond_to do |format|
format.html
format.json { render :json => @albums }
format.xml { render :xml => @albums }
end
end
def show def show
@album = Album.find( params[:id]) @album = Album.find( params[:id])
respond_to do |format| respond_to do |format|

View file

@ -0,0 +1,60 @@
class CollectionsController < ApplicationController
before_filter :require_user, :only => [:new, :create, :edit, :update, :delete, :destroy]
def index
@collections = Collection.find(:all)
respond_to do |format|
format.html
format.json { render :json => @collections }
format.xml { render :xml => @collections }
end
end
def show
@collection = Collection.find( params[:id])
respond_to do |format|
format.html
format.json { render :json => @collection }
format.xml { render :xml => @collection }
format.pdf { render :pdf => @collection.title }
end
end
def new
@collection = Collection.new
end
def create
@collection = Collection.new(params[:collection])
if @collection.save
flash[:notice] = "Collection created!"
redirect_to @collection
else
render :action => :new
end
end
def edit
@collection = Collection.find( params[:id])
end
def update
@collection = Collection.find( params[:id])
if @collection.update_attributes(params[:collection])
flash[:notice] = "collection updated!"
redirect_to @collection
else
render :action => :edit
end
end
def destroy
@collection = Collection.find( params[:id])
if @collection.destroy
redirect_to collections_path
else
redirect_to @collection
end
end
end

View file

@ -45,10 +45,13 @@ class PhotosController < ApplicationController
@photo = Photo.new(params[:photo]) @photo = Photo.new(params[:photo])
if params[:Filedata] if params[:Filedata]
@photo.swf_uploaded_data = params[:Filedata] @photo.swf_uploaded_data = params[:Filedata]
@photo.save! if @photo.save
format.html { render :text => "FILEID:" + @photo.path_modified_public("album") }
format.html { render :text => "FILEID:" + @photo.public_path_modified("album") } format.xml { render :nothing => true }
format.xml { render :nothing => true } else
format.html { render :text => "ERRORS:" + @photo.errors.full_messages.join(" "), :status => 500 }
format.xml { render :xml => @photo.errors, :status => 500 }
end
else else
if @photo.save if @photo.save
flash[:notice] = 'Created' flash[:notice] = 'Created'

View file

@ -0,0 +1,2 @@
module CollectionsHelper
end

View file

@ -1,5 +1,7 @@
class Album < ActiveRecord::Base class Album < ActiveRecord::Base
has_many :photos, :dependent => :destroy has_many :photos, :dependent => :destroy
has_many :collection_albums
has_many :collections, :through => :collection_albums
validates_uniqueness_of :path, :message => "Album already exsists on disc" validates_uniqueness_of :path, :message => "Album already exsists on disc"
@ -10,44 +12,68 @@ class Album < ActiveRecord::Base
attr_accessor :tag_list attr_accessor :tag_list
attr_protected :path attr_protected :path
protected
def self.untouched
self.find(:all, :conditions => "Albums.Id IN ( SELECT DISTINCT Photos.Album_Id FROM Photos WHERE Photos.description IS NULL AND Photos.Id NOT IN ( SELECT Photo_ID FROM Photo_Tags) )" )
end
def ensure_path def ensure_path
self.path = self.title if !self.path self.path = self.title if !self.path
end end
def tag_list def tag_list
# should maybe cache this to databse?
tags = Array.new tags = Array.new
self.photos.map{ |photo| self.photos.map{ |photo|
if photo.tags.empty? if photo.tags.empty?
# photo has no tags => no unversial tags for this album
return return
else else
photo.tags photo.tags
end }.each_with_index{ |tag,i| end
puts tag.inspect }.each_with_index{ |photo_tags,i|
tag.each { |t| # returns tag collection for each photo
puts t.title if i == 0
puts i tags = photo_tags
if i == 0 else
tags.push(t.title) # combine arrays if they have identical tags.
elsif !tags.include?(t.title) # Will remove tags that are only tagged to one photo
tags.delete(t.title) tags = tags & photo_tags
end end
} }
} return tags.collect{|tag| tag.title }.join(" ")
return tags.join(" ")
end end
def tag_list=(tags) def tag_list=(tags)
return if tags == self.tag_list return if tags == self.tag_list
current_tags = self.tag_list.split(" ")
tags = tags.split(" ")
#TODO HERE! # find tags that should be removed from this album - thus remove from all photos in album
ts = Array.new # i.e. tags listed in self.tag_list but no in parameter tags
tags.split(" ").each do |tag| #current_tags.map {|tag|tag if !tags.include?(tag) }.compact
ts.push( Tag.find_or_create_by_title( :title => tag) ) (current_tags - tags).each { |tag|
#puts "remove #{tag}"
self.photos.each {|photo|
#TODO in photo model
#photo.tag_remove( tag )
}
}
# add universial tags to all photos in album
tags.each do |tag|
#puts "tag photos with #{tag}" if !current_tags.include?( tag )
self.photos.each { |photo|
#TODO in photo model
#photo.tag_with( tag ) if !current_tags.include?( tag ) # no need to re-tag
}
end end
self.tags = ts
end end
protected
private private
def create_folders def create_folders

5
app/models/collection.rb Normal file
View file

@ -0,0 +1,5 @@
class Collection < ActiveRecord::Base
has_many :collection_albums
has_many :albums, :through => :collection_albums
end

View file

@ -0,0 +1,4 @@
class CollectionAlbum < ActiveRecord::Base
belongs_to :album
belongs_to :collection
end

View file

@ -9,7 +9,9 @@ class Photo < ActiveRecord::Base
validates_uniqueness_of :path, :message => "Photo already exsists on disc" validates_uniqueness_of :path, :message => "Photo already exsists on disc"
validates_presence_of :title validates_presence_of :title
before_create :create_thumbnails, :read_exif before_create :exif_read
after_create :create_thumbnails
before_update :exif_write # should only write if tags are changed as images can be large and thus ExifTool will take a while to write to the file
before_destroy :destroy_file before_destroy :destroy_file
attr_accessor :tag_list attr_accessor :tag_list
@ -20,20 +22,16 @@ class Photo < ActiveRecord::Base
self.find(:all, :conditions => "Photos.description IS NULL AND Photos.Id NOT IN ( SELECT Photo_ID FROM Photo_Tags)", :include => :album ) self.find(:all, :conditions => "Photos.description IS NULL AND Photos.Id NOT IN ( SELECT Photo_ID FROM Photo_Tags)", :include => :album )
end end
def path_original def extension
return APP_CONFIG[:photos_path] + self.path return File.extname(self.path_original)
end end
def path_original_public def path_original_public
return APP_CONFIG[:photos_path_public] + self.path return APP_CONFIG[:photos_path_public] + self.path
end end
def path_modified(size)
return APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_" + size + ".jpg"
end
def path_modified_public(size) def path_modified_public(size)
return APP_CONFIG[:thumbs_path_public] + self.album.path + "/" + self.id.to_s + "_" + size + ".jpg" return APP_CONFIG[:thumbs_path_public] + self.album.path + "/" + self.id.to_s + "_" + size + self.extension
end end
@ -50,40 +48,6 @@ class Photo < ActiveRecord::Base
end end
def create_thumbnails
ImageScience.with_image(APP_CONFIG[:photos_path] + self.path) do |img|
#puts " thumbing it..thumbing it.."
ext = File.extname( APP_CONFIG[:photos_path] + self.path )
img.thumbnail(85) do |thumb|
thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_thumb" + ext
end
img.thumbnail(150) do |thumb|
thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_album" + ext
end
img.thumbnail(800) do |thumb|
thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_large" + ext
end
end
end
def read_exif
photo = MiniExiftool.new(self.path_original)
self.longitude = photo.GPSLongitude
self.latitude = photo.GPSLatitude
self.title = photo.DocumentName
self.description = photo.ImageDescription
end
def write_exif
photo = MiniExiftool.new(self.path_original)
photo.GPSLongitude = self.longitude
photo.GPSLatitude = self.latitude
photo.DocumentName = self.title
photo.ImageDescription = self.description
photo.save
end
def exif_info def exif_info
photo = MiniExiftool.new(self.path_original) photo = MiniExiftool.new(self.path_original)
photo.tags.sort.each do |tag| photo.tags.sort.each do |tag|
@ -101,9 +65,54 @@ class Photo < ActiveRecord::Base
File.open(APP_CONFIG[:photos_path] + self.path, "wb") { |f| f.write(data.read) } File.open(APP_CONFIG[:photos_path] + self.path, "wb") { |f| f.write(data.read) }
end end
protected
def path_original
return APP_CONFIG[:photos_path] + self.path
end
def path_modified(size)
return APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_" + size + self.extension
end
private private
def create_thumbnails
ImageScience.with_image(APP_CONFIG[:photos_path] + self.path) do |img|
#puts " thumbing it..thumbing it.."
ext = File.extname( APP_CONFIG[:photos_path] + self.path )
img.thumbnail(85) do |thumb|
thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_thumb" + ext
end
img.thumbnail(150) do |thumb|
thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_album" + ext
end
img.thumbnail(800) do |thumb|
thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_large" + ext
end
end
end
def exif_read
photo = MiniExiftool.new(self.path_original)
self.longitude = photo.GPSLongitude if self.longitude.nil?
self.latitude = photo.GPSLatitude if self.latitude.nil?
self.title = photo.DocumentName if self.title.nil?
self.description = photo.ImageDescription if self.description.nil?
self.tag_list = photo.Keywords.map { |tag| tag.gsub(" ", "_") }.join(" ") if self.tags.empty? && !photo.Keywords.nil?
end
def exif_write
photo = MiniExiftool.new(self.path_original)
photo.GPSLongitude = self.longitude
photo.GPSLatitude = self.latitude
photo.DocumentName = self.title
photo.ImageDescription = self.description
photo.Keywords = self.tags
photo.save
end
def destroy_file def destroy_file
#puts "DELETE THUMBS OF " + APP_CONFIG[:photos_path] + self.path #puts "DELETE THUMBS OF " + APP_CONFIG[:photos_path] + self.path

View file

@ -1,6 +1,7 @@
<% for photo in @album.photos %> <% for photo in @album.photos %>
<%= link_to image_tag( photo.public_path_modified("album") ), photo %> <%= link_to image_tag( photo.path_modified_public("album") ), photo %>
<% end %> <% end %>
<br /><%= link_to "Update album", edit_album_path(@album) %> <br /><%= link_to "Update album", edit_album_path(@album) %>
<br /><%= link_to "Upload photos", upload_album_path(@album) %>
<br /><%= link_to "All albums", albums_path %> <br /><%= link_to "All albums", albums_path %>

View file

@ -0,0 +1,2 @@
<h1>Albums</h1>
<%= render :partial => @albums %>

View file

@ -7,9 +7,8 @@ $(document).ready(function() {
uploader:'/javascripts/jquery.uploadify-v1.6.2.mit/uploader.swf', uploader:'/javascripts/jquery.uploadify-v1.6.2.mit/uploader.swf',
script:'<%= photos_path %>', script:'<%= photos_path %>',
scriptData: { scriptData: {
'<%= get_session_key %>' : '<%= cookies[get_session_key] %>', '<%= get_session_key %>' : '<%= u cookies[get_session_key] %>',
'method' : '_put', '<%= request_forgery_protection_token %>' : '<%= u form_authenticity_token %>',
'authenticity_token' : '<%= u form_authenticity_token %>',
'photo[album_id]' : "<%= @album.id %>" 'photo[album_id]' : "<%= @album.id %>"
}, },
cancelImg:'/javascripts/jquery.uploadify-v1.6.2.mit/cancel.png', cancelImg:'/javascripts/jquery.uploadify-v1.6.2.mit/cancel.png',
@ -22,6 +21,8 @@ $(document).ready(function() {
image.attr('src', res.substring(7) ) image.attr('src', res.substring(7) )
image.fadeIn('slow') image.fadeIn('slow')
} }
},
onError : function (e,queueId,fileObj,errorObj,res) {
} }
}) })
}) })

View file

@ -0,0 +1,5 @@
<h1>Collections</h1>
<% for collection in @collections %>
<%= link_to collection.title, collection %>
<%= render :partial => collection.albums %>
<% end %>

View file

@ -0,0 +1 @@
<%= render :partial => @collection.albums %>

View file

@ -1,4 +1,4 @@
<li> <li>
<a href="<%= photo.public_path_modified("large") %>" title="<%= photo.title %>"> <a href="<%= photo.path_modified_public("large") %>" title="<%= photo.title %>">
<%= image_tag photo.public_path_modified("album"), { :id => 'thumb_' + photo.id.to_s } %></a> <%= image_tag photo.path_modified_public("album"), { :id => 'thumb_' + photo.id.to_s } %></a>
</li> </li>

View file

@ -6,7 +6,7 @@
<%= f.submit "Update" %> <%= f.submit "Update" %>
<% end %> <% end %>
<%= image_tag @photo.public_path_modified("large") %> <%= image_tag @photo.path_modified_public("large") %>
<br /><%= link_to("Delete photo", { :action => "destroy", :id => @photo }, <br /><%= link_to("Delete photo", { :action => "destroy", :id => @photo },
:confirm => "Are you sure you want to delete this photo?", :confirm => "Are you sure you want to delete this photo?",
:method => :delete) %> :method => :delete) %>

View file

@ -1,8 +1,9 @@
<h1><%= @photo.title%></h1> <h1><%= @photo.title%></h1>
<%= image_tag @photo.public_path_modified("large") %> <%= image_tag @photo.path_modified_public("large") %>
<br/> <br/>
Tagged with: <%= @photo.tag_list %> Tagged with: <%= @photo.tag_list %>
<p><%= @photo.description %></p> <p><%= @photo.description %></p>
<br /><%= link_to "Update photo details", edit_photo_path(@photo) %> <br /><%= link_to "Update photo details", edit_photo_path(@photo) %>
<br /><%= link_to "Back to #{@photo.album.title}", @photo.album %>
<br /><%= link_to "All albums", albums_path %> <br /><%= link_to "All albums", albums_path %>

View file

@ -19,11 +19,6 @@ Rails::Initializer.run do |config|
config.i18n.default_locale = 'no-NB' config.i18n.default_locale = 'no-NB'
config.action_controller.session = {
:session_key => '_gallery_session',
:secret => '060feafeop90cuepaiam324eoimxeaioa2b4220c445486dace48f53fc0a0d4ec4e8de033e1db323628d66b6cx990loibjustintime99'
}
config.action_mailer.smtp_settings = { config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com", :address => "smtp.gmail.com",
:port => 587, :port => 587,

View file

@ -6,7 +6,7 @@
# no regular words or you'll be exposed to dictionary attacks. # no regular words or you'll be exposed to dictionary attacks.
ActionController::Base.session = { ActionController::Base.session = {
:key => '_gallery_session', :key => '_gallery_session',
:secret => 'eb2b1c59315d0f788fd425feab3e10d78a6830dd2bf843a56ac4af333eb290781b06e6605c15d87a1539181b3a928852b76f7459e963b32fdb77e5995af0b1d6' :secret => '06xfeafeop90cuepaiam324eoimxeaioa2b4220c445486dace48f53fc1a0d4ec4e8de033e1db323628d66b6cx990loibjustintime99'
} }
# Use the database for sessions instead of the cookie-based default, # Use the database for sessions instead of the cookie-based default,
@ -14,4 +14,5 @@ ActionController::Base.session = {
# (create the session table with "rake db:sessions:create") # (create the session table with "rake db:sessions:create")
# ActionController::Base.session_store = :active_record_store # ActionController::Base.session_store = :active_record_store
ActionController::Dispatcher.middleware.use FlashSessionCookieMiddleware, ActionController::Base.session_options[:key] ActionController::Dispatcher.middleware.insert_before(ActionController::Session::CookieStore, FlashSessionCookieMiddleware, ActionController::Base.session_options[:key])
#ActionController::Dispatcher.middleware.use FlashSessionCookieMiddleware, ActionController::Base.session_options[:key]

View file

@ -7,13 +7,14 @@ ActionController::Routing::Routes.draw do |map|
map.logout "logout", :controller => "user_sessions", :action => "destroy" map.logout "logout", :controller => "user_sessions", :action => "destroy"
map.resources :photos, :collection => { :untouched => :get } map.resources :photos, :collection => { :untouched => :get }
map.resources :albums, :has_many => [ :photos ], :collection => { :untouched => :get }, :member => { :upload => :get} map.resources :albums, :collection => { :untouched => :get }, :member => { :upload => :get}, :has_many => [ :photos ]
map.resources :collections
map.resources :tags, :has_many => [ :photos ] map.resources :tags, :has_many => [ :photos ]
map.namespace :admin do |admin| map.namespace :admin do |admin|
admin.resources :users admin.resources :users
end end
map.root :controller => "albums" map.root :controller => "collections"
end end

View file

@ -0,0 +1,11 @@
class AddLocationToPhoto < ActiveRecord::Migration
def self.up
add_column :photos, :longitude, :float
add_column :photos, :latitude, :float
end
def self.down
remove_column :photos, :latitude
remove_column :photos, :longitude
end
end

View file

@ -0,0 +1,14 @@
class CreateCollections < ActiveRecord::Migration
def self.up
create_table :collections do |t|
t.string :title, :null => false
t.string :description
t.timestamps
end
end
def self.down
drop_table :collections
end
end

View file

@ -0,0 +1,14 @@
class CreateCollectionAlbums < ActiveRecord::Migration
def self.up
create_table :collection_albums do |t|
t.references :collection
t.references :album
t.timestamps
end
end
def self.down
drop_table :collection_albums
end
end

View file

@ -9,7 +9,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20090529155414) do ActiveRecord::Schema.define(:version => 20090602131547) do
create_table "albums", :force => true do |t| create_table "albums", :force => true do |t|
t.string "title", :null => false t.string "title", :null => false
@ -23,6 +23,20 @@ ActiveRecord::Schema.define(:version => 20090529155414) do
t.text "note" t.text "note"
end end
create_table "collection_albums", :force => true do |t|
t.integer "collection_id"
t.integer "album_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "collections", :force => true do |t|
t.string "title", :null => false
t.string "description"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "photo_tags", :force => true do |t| create_table "photo_tags", :force => true do |t|
t.integer "tag_id" t.integer "tag_id"
t.integer "photo_id" t.integer "photo_id"
@ -37,6 +51,8 @@ ActiveRecord::Schema.define(:version => 20090529155414) do
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.text "path" t.text "path"
t.float "longitude"
t.float "latitude"
end end
create_table "tags", :force => true do |t| create_table "tags", :force => true do |t|

View file

@ -98,6 +98,7 @@ if(jQuery)(
for (var name in settings.scriptData) { for (var name in settings.scriptData) {
scriptDataString += '&' + name + '=' + settings.scriptData[name]; scriptDataString += '&' + name + '=' + settings.scriptData[name];
} }
alert( scriptDataString )
data += '&scriptData=' + escape(scriptDataString); data += '&scriptData=' + escape(scriptDataString);
} }
data += '&btnWidth=' + settings.width; data += '&btnWidth=' + settings.width;

9
test/fixtures/collection_albums.yml vendored Normal file
View file

@ -0,0 +1,9 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
collection:
album:
two:
collection:
album:

7
test/fixtures/collections.yml vendored Normal file
View file

@ -0,0 +1,7 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
title: MyString
two:
title: MyString

View file

@ -0,0 +1,8 @@
require 'test_helper'
class CollectionsControllerTest < ActionController::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end

View file

@ -0,0 +1,8 @@
require 'test_helper'
class CollectionAlbumsTest < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end

View file

@ -0,0 +1,8 @@
require 'test_helper'
class CollectionTest < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end

View file

@ -0,0 +1,4 @@
require 'test_helper'
class CollectionsHelperTest < ActionView::TestCase
end