photo_folder 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/models/photo.rb +115 -0
- data/models/photo_collection.rb +96 -0
- data/models/photo_tag.rb +3 -0
- data/models/photo_tagging.rb +4 -0
- data/photo_folder.gemspec +2 -2
- metadata +7 -3
data/models/photo.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
class Photo < ActiveRecord::Base
|
2
|
+
belongs_to :photo_collection
|
3
|
+
has_many :photo_taggings, :dependent => :destroy
|
4
|
+
has_many :photo_tags, :through => :photo_taggings
|
5
|
+
acts_as_list :scope => :photo_collection
|
6
|
+
before_create :set_exif_data, :set_last_modified, :set_guid, :set_nsfw
|
7
|
+
after_create :set_tags
|
8
|
+
|
9
|
+
def self.guid(path,date)
|
10
|
+
Digest::MD5.hexdigest([
|
11
|
+
path,
|
12
|
+
date
|
13
|
+
].join(''))
|
14
|
+
end
|
15
|
+
|
16
|
+
def full_path
|
17
|
+
File.join(PhotoFolder.source_directory_location,path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def update_meta
|
21
|
+
set_exif_data
|
22
|
+
set_last_modified
|
23
|
+
set_guid
|
24
|
+
set_nsfw
|
25
|
+
save
|
26
|
+
set_tags
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_guid
|
30
|
+
self.guid = Photo.guid(path,date)
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_tags
|
34
|
+
#@tags was set by set_exif_data, which is always called first
|
35
|
+
self.photo_taggings.destroy_all
|
36
|
+
@tags.each do |str|
|
37
|
+
self.photo_taggings.create({
|
38
|
+
:photo_tag_id => (PhotoTag.find_by_tag(str) || PhotoTag.create(:tag => str)).id,
|
39
|
+
:photo_id => self.id
|
40
|
+
})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_nsfw
|
45
|
+
self.nsfw = @tags.collect(&:downcase).include?('nsfw') ? 1 : 0
|
46
|
+
end
|
47
|
+
|
48
|
+
def set_last_modified
|
49
|
+
self.last_modified = File.mtime(full_path)
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_exif_data
|
53
|
+
begin
|
54
|
+
exif = EXIFData.new(MiniExiftool.new(full_path),logger)
|
55
|
+
|
56
|
+
[:focal_length,:iso,:shutter_speed,:f_stop,:camera,:caption,:location,:height,:width].each do |key|
|
57
|
+
self.send(key.to_s + '=',exif[key] || nil)
|
58
|
+
end
|
59
|
+
|
60
|
+
#date,title,lens and tags are special cases
|
61
|
+
if exif[:date].is_a? Time
|
62
|
+
self.date = exif[:date]
|
63
|
+
else
|
64
|
+
date_match = (exif[:date] || '').match(/([\d]+):([\d]+):([\d]+) ([\d]+):([\d]+):([\d]+)/)
|
65
|
+
self.date = Time.mktime(date_match[1],date_match[2],date_match[3],date_match[4],date_match[5],date_match[6]) if date_match
|
66
|
+
end
|
67
|
+
self.name = exif[:title] || full_path.split('/').pop.gsub(/\.[a-zA-Z]{1,4}/,'')
|
68
|
+
self.lens = exif[:lens] ? exif[:lens] : nil
|
69
|
+
@tags = exif[:tags] || []
|
70
|
+
rescue
|
71
|
+
self.name = full_path.split('/').pop.gsub(/\.[a-zA-Z]{1,4}/,'')
|
72
|
+
@tags = []
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class EXIFData
|
77
|
+
EXIF_TRANSLATIONS = {
|
78
|
+
:title => ['Title','ObjectName'],
|
79
|
+
:focal_length => ['FocalLength'],
|
80
|
+
:iso => ['ISO'],
|
81
|
+
:height => ['ImageHeight'],
|
82
|
+
:width => ['ImageWidth'],
|
83
|
+
:shutter_speed => ['ShutterSpeedValue'],
|
84
|
+
:f_stop => ['ApertureValue'],
|
85
|
+
:lens => ['Lens','LensType'],
|
86
|
+
:camera => ['Model'],
|
87
|
+
:date => ['DateTimeOriginal'],
|
88
|
+
:caption => ['Description','ImageDescription','Caption-Abstract'],
|
89
|
+
:tags => ['Keywords','Subject'],
|
90
|
+
:location => ['Location'],
|
91
|
+
}
|
92
|
+
|
93
|
+
EXIF_TRANSFORMATIONS = {
|
94
|
+
#:date => lambda{|exif_value| exif_value.to_s.split('-').shift},
|
95
|
+
:shutter_speed => lambda{|exif_value| exif_value.to_s.gsub(/1\//,'')},
|
96
|
+
:focal_length => lambda{|exif_value| exif_value.to_s.gsub(/\.([\d]{1,})?\s?.+$/,'')},
|
97
|
+
:tags => lambda{|exif_value| (exif_value.is_a?(Array) ? exif_value.join(',') : exif_value).gsub(/["']+/,'').gsub(/\s+?,\s+?/,',').split(',').collect(&:strip).collect(&:downcase)}
|
98
|
+
}
|
99
|
+
|
100
|
+
def initialize(exif_data,logger)
|
101
|
+
@exif_data = exif_data
|
102
|
+
@logger = logger
|
103
|
+
end
|
104
|
+
|
105
|
+
def [](key)
|
106
|
+
EXIF_TRANSLATIONS[key.to_sym].each do |exif_key_name|
|
107
|
+
exif_value = @exif_data[exif_key_name.to_s]
|
108
|
+
if !exif_value.nil? && exif_value != false && exif_value != '' && exif_value != 'false' && exif_value != 'nil'
|
109
|
+
return EXIF_TRANSFORMATIONS[key] ? EXIF_TRANSFORMATIONS[key].call(exif_value) : exif_value
|
110
|
+
end
|
111
|
+
end
|
112
|
+
false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
class PhotoCollection < ActiveRecord::Base
|
2
|
+
has_many :photos, :order => 'position'
|
3
|
+
acts_as_list :scope => :parent_id
|
4
|
+
acts_as_tree :order => :name
|
5
|
+
after_create :set_children_parent_id
|
6
|
+
before_create :set_name
|
7
|
+
|
8
|
+
def self.set_correct_positions(collections,is_callback = false)
|
9
|
+
collections.sort_by(&:name).each_with_index do |collection,i|
|
10
|
+
collection.update_attribute :position, i
|
11
|
+
set_correct_positions(PhotoCollection.find_all_by_parent_id(collection.id),true)
|
12
|
+
end
|
13
|
+
if self.positions && !is_callback
|
14
|
+
self.positions.each_with_index do |file_name,i|
|
15
|
+
photo_collection = PhotoCollection.find_by_path(file_name,{
|
16
|
+
:conditions => {
|
17
|
+
:parent_id => 0
|
18
|
+
}
|
19
|
+
})
|
20
|
+
if photo_collection
|
21
|
+
photo_collection.insert_at i + 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.positions_file_path
|
28
|
+
File.join(PhotoFolder.source_directory_location,'positions.yml')
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.positions
|
32
|
+
return @positions if !@positions.nil?
|
33
|
+
if File.exists?(self.positions_file_path)
|
34
|
+
@positions = YAML.load(File.read(self.positions_file_path))
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_children_parent_id
|
41
|
+
PhotoFolder::all_paths_in_database.select{|path| self.path.underscore.gsub(/\s/,'_') == path.gsub(/\/[^\/]+$/,'').underscore.gsub(/\s/,'_')}.each do |path|
|
42
|
+
Photo.update_all("photo_collection_id = #{self.id}","path = '#{path}'")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def set_parent_id
|
47
|
+
update_attribute :parent_id, parent_from_path ? parent_from_path.id : 0
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_name
|
51
|
+
self.name = path.split('/').pop.gsub(/[\_\-]+/,' ').split(/\s+/).each(&:capitalize!).join(' ')
|
52
|
+
end
|
53
|
+
|
54
|
+
def parent_from_path
|
55
|
+
self.path.count('/') > 0 ? PhotoCollection.find_by_path(self.path.gsub(/\/[^\/]+$/,'')) : false
|
56
|
+
end
|
57
|
+
|
58
|
+
def full_path
|
59
|
+
File.join(PhotoFolder.source_directory_location,path)
|
60
|
+
end
|
61
|
+
|
62
|
+
def positions_file_path
|
63
|
+
File.join(full_path,'positions.yml')
|
64
|
+
end
|
65
|
+
|
66
|
+
def positions
|
67
|
+
return @positions if !@positions.nil?
|
68
|
+
if File.exists?(positions_file_path)
|
69
|
+
@positions = YAML.load(File.read(positions_file_path))
|
70
|
+
else
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def meta_file_path
|
76
|
+
File.join(full_path,'meta.json')
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_meta
|
80
|
+
meta_data = File.exists?(meta_file_path) ? File.read(meta_file_path) : false
|
81
|
+
write_attribute :meta, meta_data
|
82
|
+
meta_data
|
83
|
+
end
|
84
|
+
|
85
|
+
def set_correct_positions
|
86
|
+
positions.each_with_index do |file_name,i|
|
87
|
+
photo = photos.find_by_path("#{path}/#{file_name}")
|
88
|
+
photo_collection = children.find_by_path("#{path}/#{file_name}")
|
89
|
+
if photo
|
90
|
+
photo.insert_at i + 1
|
91
|
+
elsif photo_collection
|
92
|
+
photo_collection.insert_at i + 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/models/photo_tag.rb
ADDED
data/photo_folder.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "photo_folder"
|
3
|
-
s.version = "1.0.
|
3
|
+
s.version = "1.0.3"
|
4
4
|
s.date = "2010-05-11"
|
5
5
|
s.summary = "JavaScript gallery"
|
6
6
|
s.email = "ryan@syntacticx.com"
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.files = [
|
12
12
|
"README.markdown",
|
13
13
|
"photo_folder.gemspec"] +
|
14
|
-
Dir['
|
14
|
+
Dir['models/**/*'] +
|
15
15
|
Dir['vendor/**/*']
|
16
16
|
s.autorequire = "lib/photo_folder.rb"
|
17
17
|
s.add_dependency("sqlite3-ruby", ["> 0.0.0"])
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: photo_folder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 3
|
10
|
+
version: 1.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Johnson
|
@@ -61,6 +61,10 @@ extra_rdoc_files: []
|
|
61
61
|
files:
|
62
62
|
- README.markdown
|
63
63
|
- photo_folder.gemspec
|
64
|
+
- models/photo.rb
|
65
|
+
- models/photo_collection.rb
|
66
|
+
- models/photo_tag.rb
|
67
|
+
- models/photo_tagging.rb
|
64
68
|
- vendor/acts_as_list.rb
|
65
69
|
- vendor/acts_as_tree.rb
|
66
70
|
- vendor/mini_exiftool.rb
|