photo_folder 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
         |