attachment-san 0.0.1 → 0.0.2
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/TODO +1 -4
- data/VERSION +1 -1
- data/attachment-san.gemspec +6 -2
- data/lib/attachment_san.rb +2 -1
- data/lib/attachment_san/core_ext.rb +32 -0
- data/lib/attachment_san/has.rb +25 -18
- data/lib/attachment_san/variant.rb +21 -7
- data/rails/init.rb +1 -0
- data/test/attachment_san_test.rb +6 -4
- data/test/core_ext_test.rb +17 -0
- data/test/fixtures/models/document.rb +17 -21
- data/test/has_test.rb +65 -35
- data/test/lib/schema.rb +3 -2
- data/test/variant_test.rb +37 -13
- metadata +5 -2
    
        data/TODO
    CHANGED
    
    | @@ -1,6 +1,3 @@ | |
| 1 | 
            -
            *  | 
| 2 | 
            -
              * has_attachment :watermark, :superclass => WatermarkSuperclass
         | 
| 3 | 
            -
              * has_attachment :watermark, :class => WatermarkClass
         | 
| 4 | 
            -
            * Nest created classes under the superclass.
         | 
| 1 | 
            +
            * Allow the user to override any of the attachment_san_options on the dynamically created attachment subclasses.
         | 
| 5 2 | 
             
            * Do we need to sanitize the original filename, eg lowercase.
         | 
| 6 3 | 
             
            * Make :filename_scheme => :record_identifier also use nesting under parent resources. Eg /resources/1/images/2/filename
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.0. | 
| 1 | 
            +
            0.0.2
         | 
    
        data/attachment-san.gemspec
    CHANGED
    
    | @@ -5,11 +5,11 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            Gem::Specification.new do |s|
         | 
| 7 7 | 
             
              s.name = %q{attachment-san}
         | 
| 8 | 
            -
              s.version = "0.0. | 
| 8 | 
            +
              s.version = "0.0.2"
         | 
| 9 9 |  | 
| 10 10 | 
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 11 11 | 
             
              s.authors = ["Eloy Duran", "Manfred Stienstra"]
         | 
| 12 | 
            -
              s.date = %q{2009- | 
| 12 | 
            +
              s.date = %q{2009-12-01}
         | 
| 13 13 | 
             
              s.description = %q{Rails plugin for easy and rich attachment manipulation.}
         | 
| 14 14 | 
             
              s.email = ["eloy@fngtps.com", "manfred@fngtps.com"]
         | 
| 15 15 | 
             
              s.extra_rdoc_files = [
         | 
| @@ -22,10 +22,12 @@ Gem::Specification.new do |s| | |
| 22 22 | 
             
                 "Rakefile",
         | 
| 23 23 | 
             
                 "TODO",
         | 
| 24 24 | 
             
                 "VERSION",
         | 
| 25 | 
            +
                 "attachment-san.gemspec",
         | 
| 25 26 | 
             
                 "examples/photo.rb",
         | 
| 26 27 | 
             
                 "examples/photos_controller.rb",
         | 
| 27 28 | 
             
                 "examples/post.rb",
         | 
| 28 29 | 
             
                 "lib/attachment_san.rb",
         | 
| 30 | 
            +
                 "lib/attachment_san/core_ext.rb",
         | 
| 29 31 | 
             
                 "lib/attachment_san/has.rb",
         | 
| 30 32 | 
             
                 "lib/attachment_san/test/helper.rb",
         | 
| 31 33 | 
             
                 "lib/attachment_san/test/rails.png",
         | 
| @@ -33,6 +35,7 @@ Gem::Specification.new do |s| | |
| 33 35 | 
             
                 "napkin.rb",
         | 
| 34 36 | 
             
                 "rails/init.rb",
         | 
| 35 37 | 
             
                 "test/attachment_san_test.rb",
         | 
| 38 | 
            +
                 "test/core_ext_test.rb",
         | 
| 36 39 | 
             
                 "test/fixtures/models/attachment.rb",
         | 
| 37 40 | 
             
                 "test/fixtures/models/document.rb",
         | 
| 38 41 | 
             
                 "test/fixtures/models/options_stub.rb",
         | 
| @@ -48,6 +51,7 @@ Gem::Specification.new do |s| | |
| 48 51 | 
             
              s.summary = %q{Rails plugin for easy and rich attachment manipulation.}
         | 
| 49 52 | 
             
              s.test_files = [
         | 
| 50 53 | 
             
                "test/attachment_san_test.rb",
         | 
| 54 | 
            +
                 "test/core_ext_test.rb",
         | 
| 51 55 | 
             
                 "test/fixtures/models/attachment.rb",
         | 
| 52 56 | 
             
                 "test/fixtures/models/document.rb",
         | 
| 53 57 | 
             
                 "test/fixtures/models/options_stub.rb",
         | 
    
        data/lib/attachment_san.rb
    CHANGED
    
    | @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            require "attachment_san/core_ext"
         | 
| 1 2 | 
             
            require "attachment_san/has"
         | 
| 2 3 | 
             
            require "attachment_san/variant"
         | 
| 3 4 |  | 
| @@ -35,7 +36,7 @@ module AttachmentSan | |
| 35 36 |  | 
| 36 37 | 
             
                @uploaded_file    = uploaded_file
         | 
| 37 38 | 
             
                self.filename     = uploaded_file.original_filename
         | 
| 38 | 
            -
                self.content_type = uploaded_file.content_type
         | 
| 39 | 
            +
                self.content_type = uploaded_file.content_type.strip
         | 
| 39 40 |  | 
| 40 41 | 
             
                callback :after_upload
         | 
| 41 42 | 
             
              end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            module AttachmentSan
         | 
| 2 | 
            +
              module ModuleExt
         | 
| 3 | 
            +
                # Retrieve a Module/Class bfor the given +name+. It differentiates from
         | 
| 4 | 
            +
                # +const_get+ in that it _only_ searches in the mod it’s called on.
         | 
| 5 | 
            +
                #
         | 
| 6 | 
            +
                #   class A
         | 
| 7 | 
            +
                #     class B
         | 
| 8 | 
            +
                #     end
         | 
| 9 | 
            +
                #   end
         | 
| 10 | 
            +
                #
         | 
| 11 | 
            +
                #   class C; end
         | 
| 12 | 
            +
                #
         | 
| 13 | 
            +
                #   # If the requested mod exists in the namespace, the result is the same:
         | 
| 14 | 
            +
                #   A.const_get('B') # => A::B
         | 
| 15 | 
            +
                #   A.modulized_mod_get('B') # => A::B
         | 
| 16 | 
            +
                #
         | 
| 17 | 
            +
                #   # Now notice that const_get finds the mod outside the `A' namespace:
         | 
| 18 | 
            +
                #   A.const_get('C') # => C
         | 
| 19 | 
            +
                #   A.modulized_mod_get('C') # => NameError
         | 
| 20 | 
            +
                def modulized_mod_get(name)
         | 
| 21 | 
            +
                  const = const_get(name)
         | 
| 22 | 
            +
                  modulized_name = "#{self.name}::#{name}"
         | 
| 23 | 
            +
                  
         | 
| 24 | 
            +
                  if const.is_a?(Module) && const.name == modulized_name
         | 
| 25 | 
            +
                    const
         | 
| 26 | 
            +
                  else
         | 
| 27 | 
            +
                    raise NameError, "uninitialized mod constant #{modulized_name}"
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
              Module.send(:include, ModuleExt)
         | 
| 32 | 
            +
            end
         | 
    
        data/lib/attachment_san/has.rb
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            module AttachmentSan
         | 
| 2 2 | 
             
              module Has
         | 
| 3 | 
            -
                 | 
| 3 | 
            +
                MODEL_OPTIONS   = [:base_path, :public_base_path, :extension, :filename_scheme]
         | 
| 4 | 
            +
                VARIANT_OPTIONS = [:name, :process, :class, :variants, :filename_scheme]
         | 
| 4 5 |  | 
| 5 6 | 
             
                def has_attachment(name, options = {})
         | 
| 6 7 | 
             
                  define_attachment_association :has_one, name, options
         | 
| @@ -13,37 +14,43 @@ module AttachmentSan | |
| 13 14 | 
             
                private
         | 
| 14 15 |  | 
| 15 16 | 
             
                def define_attachment_association(macro, name, options)
         | 
| 16 | 
            -
                   | 
| 17 | 
            -
                   | 
| 17 | 
            +
                  model_options = extract_options!(options, MODEL_OPTIONS)
         | 
| 18 | 
            +
                  model = create_model(name, model_options)
         | 
| 19 | 
            +
                  
         | 
| 20 | 
            +
                  variant_options = extract_options!(options, VARIANT_OPTIONS)
         | 
| 21 | 
            +
                  define_variants(model, variant_options)
         | 
| 22 | 
            +
                  
         | 
| 23 | 
            +
                  send(macro, name, options.merge(:class_name => model.name)) unless reflect_on_association(name)
         | 
| 18 24 | 
             
                end
         | 
| 19 25 |  | 
| 20 | 
            -
                def  | 
| 26 | 
            +
                def extract_options!(options, keys)
         | 
| 21 27 | 
             
                  options.symbolize_keys!
         | 
| 22 | 
            -
                   | 
| 23 | 
            -
                  options.except!(* | 
| 24 | 
            -
                   | 
| 28 | 
            +
                  extracted_options = options.slice(*keys)
         | 
| 29 | 
            +
                  options.except!(*keys)
         | 
| 30 | 
            +
                  extracted_options
         | 
| 25 31 | 
             
                end
         | 
| 26 32 |  | 
| 27 | 
            -
                def define_variants( | 
| 28 | 
            -
                   | 
| 29 | 
            -
                  
         | 
| 30 | 
            -
                  original = { :class => Variant::Original }
         | 
| 31 | 
            -
                  original.merge!(options) unless options.has_key?(:variants)
         | 
| 33 | 
            +
                def define_variants(model, options)
         | 
| 34 | 
            +
                  original = options[:variants] ? (options[:variants][:original] || {}) : options
         | 
| 35 | 
            +
                  original[:class] ||= Variant::Original if original.is_a?(Hash)
         | 
| 32 36 | 
             
                  model.send(:define_variant, :original, original)
         | 
| 33 37 |  | 
| 34 38 | 
             
                  if variants = options[:variants]
         | 
| 35 | 
            -
                    variants.each do |name,  | 
| 36 | 
            -
                      model.send(:define_variant, name,  | 
| 39 | 
            +
                    variants.each do |name, variant_options|
         | 
| 40 | 
            +
                      model.send(:define_variant, name, variant_options)
         | 
| 37 41 | 
             
                    end
         | 
| 38 42 | 
             
                  end
         | 
| 43 | 
            +
                  
         | 
| 44 | 
            +
                  model
         | 
| 39 45 | 
             
                end
         | 
| 40 46 |  | 
| 41 | 
            -
                 | 
| 42 | 
            -
                def create_model(name)
         | 
| 47 | 
            +
                def create_model(name, options)
         | 
| 43 48 | 
             
                  name = name.to_s.classify
         | 
| 44 | 
            -
                   | 
| 49 | 
            +
                  modulized_mod_get(name)
         | 
| 45 50 | 
             
                rescue NameError
         | 
| 46 | 
            -
                   | 
| 51 | 
            +
                  model = const_set(name, Class.new(AttachmentSan.attachment_class))
         | 
| 52 | 
            +
                  model.attachment_san_options.merge!(options)
         | 
| 53 | 
            +
                  model
         | 
| 47 54 | 
             
                end
         | 
| 48 55 | 
             
              end
         | 
| 49 56 | 
             
            end
         | 
| @@ -27,7 +27,7 @@ module AttachmentSan | |
| 27 27 | 
             
                      when Proc
         | 
| 28 28 | 
             
                        { :class => Variant, :process => x }
         | 
| 29 29 | 
             
                      when nil
         | 
| 30 | 
            -
                        { :class =>  | 
| 30 | 
            +
                        { :class => modulized_mod_get(name.to_s.camelize) }
         | 
| 31 31 | 
             
                      else
         | 
| 32 32 | 
             
                        raise TypeError, "Please specify a options hash, variant class, or process proc. Can't use `#{x.inspect}'."
         | 
| 33 33 | 
             
                      end
         | 
| @@ -65,11 +65,11 @@ module AttachmentSan | |
| 65 65 | 
             
                end
         | 
| 66 66 |  | 
| 67 67 | 
             
                def base_path
         | 
| 68 | 
            -
                  base_options[:base_path]
         | 
| 68 | 
            +
                  @reflection[:base_path] || base_options[:base_path]
         | 
| 69 69 | 
             
                end
         | 
| 70 70 |  | 
| 71 71 | 
             
                def public_base_path
         | 
| 72 | 
            -
                  base_options[:public_base_path]
         | 
| 72 | 
            +
                  @reflection[:public_base_path] || base_options[:public_base_path]
         | 
| 73 73 | 
             
                end
         | 
| 74 74 |  | 
| 75 75 | 
             
                def filename_scheme
         | 
| @@ -92,6 +92,11 @@ module AttachmentSan | |
| 92 92 | 
             
                  @record.token.scan(/.{2}/)
         | 
| 93 93 | 
             
                end
         | 
| 94 94 |  | 
| 95 | 
            +
                # Returns the original filename, without extension, and appends the variant name.
         | 
| 96 | 
            +
                def filename_with_variant_name
         | 
| 97 | 
            +
                  "#{@record.filename_without_extension}.#{name}"
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
                
         | 
| 95 100 | 
             
                def filename
         | 
| 96 101 | 
             
                  unless @filename
         | 
| 97 102 | 
             
                    @filename = 
         | 
| @@ -99,12 +104,13 @@ module AttachmentSan | |
| 99 104 | 
             
                      when :variant_name
         | 
| 100 105 | 
             
                        name.to_s
         | 
| 101 106 | 
             
                      when :keep_original
         | 
| 102 | 
            -
                         | 
| 107 | 
            +
                        filename_with_variant_name
         | 
| 103 108 | 
             
                      when :record_identifier
         | 
| 104 | 
            -
                         | 
| 109 | 
            +
                        # For now we take only the demodulized attachment class name.
         | 
| 110 | 
            +
                        @record_class_name ||= @record.class.name.demodulize.underscore.pluralize
         | 
| 105 111 | 
             
                        "/#{@record_class_name}/#{@record.to_param}/#{name}"
         | 
| 106 112 | 
             
                      when :token
         | 
| 107 | 
            -
                        File.join(token,  | 
| 113 | 
            +
                        File.join(token, filename_with_variant_name)
         | 
| 108 114 | 
             
                      else
         | 
| 109 115 | 
             
                        raise ArgumentError, "The :filename_scheme option should be one of `:token', `:filename_scheme', `:record_identifier', or `:variant_name', it currently is `#{filename_scheme.inspect}'."
         | 
| 110 116 | 
             
                      end
         | 
| @@ -140,7 +146,15 @@ module AttachmentSan | |
| 140 146 | 
             
                  end
         | 
| 141 147 |  | 
| 142 148 | 
             
                  def filename
         | 
| 143 | 
            -
                    @filename ||= | 
| 149 | 
            +
                    @filename ||=
         | 
| 150 | 
            +
                      case filename_scheme
         | 
| 151 | 
            +
                      when :token
         | 
| 152 | 
            +
                        File.join(token, @record.filename)
         | 
| 153 | 
            +
                      when :keep_original
         | 
| 154 | 
            +
                        @record.filename
         | 
| 155 | 
            +
                      else
         | 
| 156 | 
            +
                        super
         | 
| 157 | 
            +
                      end
         | 
| 144 158 | 
             
                  end
         | 
| 145 159 |  | 
| 146 160 | 
             
                  def process!
         | 
    
        data/rails/init.rb
    CHANGED
    
    
    
        data/test/attachment_san_test.rb
    CHANGED
    
    | @@ -76,8 +76,8 @@ describe "AttachmentSan, class methods" do | |
| 76 76 | 
             
              end
         | 
| 77 77 |  | 
| 78 78 | 
             
              it "should define a variant with options" do
         | 
| 79 | 
            -
                Logo.variant_reflections.map { |r| r[:name] }.should == [:original, :header]
         | 
| 80 | 
            -
                Logo.new.header.should.be.instance_of MyVariant
         | 
| 79 | 
            +
                Document::Logo.variant_reflections.map { |r| r[:name] }.should == [:original, :header]
         | 
| 80 | 
            +
                Document::Logo.new.header.should.be.instance_of MyVariant
         | 
| 81 81 | 
             
              end
         | 
| 82 82 | 
             
            end
         | 
| 83 83 |  | 
| @@ -95,8 +95,10 @@ describe "AttachmentSan, instance methods" do | |
| 95 95 | 
             
                @attachment.filename.should == @upload.original_filename
         | 
| 96 96 | 
             
              end
         | 
| 97 97 |  | 
| 98 | 
            -
              it "should  | 
| 99 | 
            -
                @ | 
| 98 | 
            +
              it "should strip the content type and assign to the model" do
         | 
| 99 | 
            +
                @upload.stubs(:content_type).returns("\simage/png\r\n")
         | 
| 100 | 
            +
                @attachment = Attachment.new(:uploaded_file => @upload)
         | 
| 101 | 
            +
                @attachment.content_type.should == 'image/png'
         | 
| 100 102 | 
             
              end
         | 
| 101 103 |  | 
| 102 104 | 
             
              it "should return the original file's extension" do
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            require File.expand_path('../test_helper', __FILE__)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module CoreExtSpecs
         | 
| 4 | 
            +
              class Foo
         | 
| 5 | 
            +
                class Bar; end
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
              
         | 
| 8 | 
            +
              class Baz; end
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            describe "Module" do
         | 
| 12 | 
            +
              it "should try to retrieve a constant by the full modulized name of the mod it’s called on" do
         | 
| 13 | 
            +
                # ActiveSupport::Dependencies raises an ArgumentError instead of NameError... :(
         | 
| 14 | 
            +
                lambda { CoreExtSpecs::Foo.modulized_mod_get('Baz') }.should.raise ArgumentError
         | 
| 15 | 
            +
                CoreExtSpecs::Foo.modulized_mod_get('Bar').should.be CoreExtSpecs::Foo::Bar
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -1,39 +1,35 @@ | |
| 1 1 | 
             
            class MyVariant < AttachmentSan::Variant
         | 
| 2 | 
            -
              def process | 
| 3 | 
            -
              end
         | 
| 2 | 
            +
              def process!; end
         | 
| 4 3 | 
             
            end
         | 
| 5 4 |  | 
| 6 | 
            -
            class  | 
| 7 | 
            -
              def  | 
| 8 | 
            -
              end
         | 
| 5 | 
            +
            class MyOtherVariant < AttachmentSan::Variant
         | 
| 6 | 
            +
              def process!; end
         | 
| 9 7 | 
             
            end
         | 
| 10 8 |  | 
| 11 | 
            -
            class  | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
              end
         | 
| 17 | 
            -
              
         | 
| 18 | 
            -
              class BigCard < AttachmentSan::Variant
         | 
| 19 | 
            -
                def process!
         | 
| 20 | 
            -
                  puts 'BIG!'
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
              end
         | 
| 9 | 
            +
            class MyOriginal < AttachmentSan::Variant::Original
         | 
| 10 | 
            +
            end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            class MyProcessor
         | 
| 13 | 
            +
              def initialize(variant); end
         | 
| 23 14 | 
             
            end
         | 
| 24 15 |  | 
| 25 16 | 
             
            class Document < ActiveRecord::Base
         | 
| 26 | 
            -
              extend AttachmentSan::Has
         | 
| 27 | 
            -
              
         | 
| 28 17 | 
             
              has_attachment  :watermark
         | 
| 29 18 | 
             
              has_attachment  :logo, :variants => { :header => MyVariant }
         | 
| 30 19 |  | 
| 31 | 
            -
              has_attachments :misc_files, :filename_scheme => :keep_original, :process => proc { :from_process_proc }
         | 
| 20 | 
            +
              has_attachments :misc_files, :class => MyOriginal, :filename_scheme => :keep_original, :process => proc { :from_process_proc }
         | 
| 32 21 | 
             
              has_attachments :images, :variants => {
         | 
| 33 22 | 
             
                :thumbnail => proc { |v| MyProcessor.new(v) },
         | 
| 34 23 | 
             
                :medium_sized => proc {},
         | 
| 35 24 | 
             
                :download => proc {}
         | 
| 36 25 | 
             
              }
         | 
| 26 | 
            +
            end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            class OtherDocument < ActiveRecord::Base
         | 
| 29 | 
            +
              has_attachment  :logo, :variants => { :header => MyOtherVariant }
         | 
| 30 | 
            +
              has_attachments :misc_files, :filename_scheme => :keep_original, :process => proc { :from_other_process_proc }
         | 
| 37 31 |  | 
| 38 | 
            -
              has_attachments : | 
| 32 | 
            +
              has_attachments :images, :base_path => '/other/base', :public_base_path => '/other/public', :variants => {
         | 
| 33 | 
            +
                :normal => { :base_path => '/yet/another/base', :process => proc {} }
         | 
| 34 | 
            +
              }
         | 
| 39 35 | 
             
            end
         | 
    
        data/test/has_test.rb
    CHANGED
    
    | @@ -1,34 +1,71 @@ | |
| 1 1 | 
             
            require File.expand_path('../test_helper', __FILE__)
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe "AttachmentSan::Has" do
         | 
| 4 | 
            +
              process_proc = proc {}
         | 
| 5 | 
            +
              
         | 
| 4 6 | 
             
              it "should pass on any unknown options to the has_one macro" do
         | 
| 5 | 
            -
                Document.expects(:has_one).with(:other_file, :as => :attachable, :order => :updated_at)
         | 
| 6 | 
            -
                Document.expects(:define_variants).with | 
| 7 | 
            +
                Document.expects(:has_one).with(:other_file, :as => :attachable, :order => :updated_at, :class_name => 'Document::OtherFile')
         | 
| 8 | 
            +
                Document.expects(:define_variants).with do |model, options|
         | 
| 9 | 
            +
                  model == Document::OtherFile && options == { :process => process_proc, :class => MyVariant }
         | 
| 10 | 
            +
                end
         | 
| 7 11 |  | 
| 8 12 | 
             
                Document.has_attachment :other_file, :as => :attachable, :order => :updated_at,
         | 
| 9 | 
            -
                                                     :process =>  | 
| 13 | 
            +
                                                     :process => process_proc, :class => MyVariant, :filename_scheme => :token
         | 
| 10 14 | 
             
              end
         | 
| 11 15 |  | 
| 12 16 | 
             
              it "should pass on any unknown options to the has_many macro" do
         | 
| 13 | 
            -
                Document.expects(:has_many).with(:other_files, :as => :attachable, :order => :updated_at)
         | 
| 14 | 
            -
                Document.expects(:define_variants).with | 
| 17 | 
            +
                Document.expects(:has_many).with(:other_files, :as => :attachable, :order => :updated_at, :class_name => 'Document::OtherFile')
         | 
| 18 | 
            +
                Document.expects(:define_variants).with do |model, options|
         | 
| 19 | 
            +
                  model == Document::OtherFile && options == { :process => process_proc, :class => MyVariant }
         | 
| 20 | 
            +
                end
         | 
| 15 21 |  | 
| 16 22 | 
             
                Document.has_attachments :other_files, :as => :attachable, :order => :updated_at,
         | 
| 17 | 
            -
                                                       :process =>  | 
| 23 | 
            +
                                                       :process => process_proc, :class => MyVariant, :filename_scheme => :token
         | 
| 18 24 | 
             
              end
         | 
| 19 25 |  | 
| 20 26 | 
             
              it "should not define an association if an association for the given name exists" do
         | 
| 21 27 | 
             
                Document.expects(:has_one).never
         | 
| 22 | 
            -
                Document.expects(:define_variants).with | 
| 28 | 
            +
                Document.expects(:define_variants).with do |model, options|
         | 
| 29 | 
            +
                  model == Document::Watermark && options == {}
         | 
| 30 | 
            +
                end
         | 
| 23 31 |  | 
| 24 32 | 
             
                Document.expects(:has_many).never
         | 
| 25 | 
            -
                Document.expects(:define_variants).with | 
| 33 | 
            +
                Document.expects(:define_variants).with do |model, options|
         | 
| 34 | 
            +
                  model == Document::Image && options == {}
         | 
| 35 | 
            +
                end
         | 
| 26 36 |  | 
| 27 37 | 
             
                Document.has_attachment :watermark, :as => :attachable
         | 
| 28 38 | 
             
                Document.has_attachments :images, :as => :attachable
         | 
| 29 39 | 
             
              end
         | 
| 30 40 | 
             
            end
         | 
| 31 41 |  | 
| 42 | 
            +
            describe "AttachmentSan::Has, concerning defining attachment model subclasses" do
         | 
| 43 | 
            +
              it "should create an attachment model class when defining a single attachment association" do
         | 
| 44 | 
            +
                Document.reflect_on_association(:logo).klass.should.be Document::Logo
         | 
| 45 | 
            +
                Document::Logo.superclass.should.be AttachmentSan.attachment_class
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
              
         | 
| 48 | 
            +
              it "should create an attachment model class when defining a collection attachment association" do
         | 
| 49 | 
            +
                Document.reflect_on_association(:images).klass.should.be Document::Image
         | 
| 50 | 
            +
                Document::Image.superclass.should.be AttachmentSan.attachment_class
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
              
         | 
| 53 | 
            +
              it "should create different attachment model classes for different defining model classes" do
         | 
| 54 | 
            +
                Document::Logo.reflect_on_variant(:header)[:class].should.be MyVariant
         | 
| 55 | 
            +
                
         | 
| 56 | 
            +
                OtherDocument.reflect_on_association(:logo).klass.should.be OtherDocument::Logo
         | 
| 57 | 
            +
                OtherDocument::Logo.reflect_on_variant(:header)[:class].should.be MyOtherVariant
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
              
         | 
| 60 | 
            +
              it "should not look for existing constants outside the defining class's namespace" do
         | 
| 61 | 
            +
                class TotallyDifferent; end
         | 
| 62 | 
            +
                class Foo < TotallyDifferent; end
         | 
| 63 | 
            +
                
         | 
| 64 | 
            +
                Document.has_attachment :foo
         | 
| 65 | 
            +
                Document.reflect_on_association(:foo).klass.should.be Document::Foo
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
            end
         | 
| 68 | 
            +
             | 
| 32 69 | 
             
            describe "AttachmentSan::Has, concerning a single associated attachment" do
         | 
| 33 70 | 
             
              before do
         | 
| 34 71 | 
             
                @document = Document.new
         | 
| @@ -36,21 +73,18 @@ describe "AttachmentSan::Has, concerning a single associated attachment" do | |
| 36 73 | 
             
                @document.build_watermark :uploaded_file => rails_icon
         | 
| 37 74 | 
             
              end
         | 
| 38 75 |  | 
| 39 | 
            -
              it "should  | 
| 40 | 
            -
                 | 
| 41 | 
            -
                reflection.macro.should == :has_one
         | 
| 42 | 
            -
                reflection.klass.should == Logo
         | 
| 43 | 
            -
                Logo.superclass.should.be AttachmentSan.attachment_class
         | 
| 76 | 
            +
              it "should define a has_one association" do
         | 
| 77 | 
            +
                Document.reflect_on_association(:logo).macro.should == :has_one
         | 
| 44 78 | 
             
              end
         | 
| 45 79 |  | 
| 46 80 | 
             
              it "should store the variant options on the new model class" do
         | 
| 47 | 
            -
                Watermark.variant_reflections.length.should == 1
         | 
| 48 | 
            -
                Watermark.variant_reflections.first[:name].should == :original
         | 
| 49 | 
            -
                Watermark.variant_reflections.first[:class].should == AttachmentSan::Variant::Original
         | 
| 81 | 
            +
                Document::Watermark.variant_reflections.length.should == 1
         | 
| 82 | 
            +
                Document::Watermark.variant_reflections.first[:name].should == :original
         | 
| 83 | 
            +
                Document::Watermark.variant_reflections.first[:class].should == AttachmentSan::Variant::Original
         | 
| 50 84 |  | 
| 51 | 
            -
                Logo.variant_reflections.length.should == 2
         | 
| 52 | 
            -
                Logo.variant_reflections.last[:name].should == :header
         | 
| 53 | 
            -
                Logo.variant_reflections.last[:class].should == MyVariant
         | 
| 85 | 
            +
                Document::Logo.variant_reflections.length.should == 2
         | 
| 86 | 
            +
                Document::Logo.variant_reflections.last[:name].should == :header
         | 
| 87 | 
            +
                Document::Logo.variant_reflections.last[:class].should == MyVariant
         | 
| 54 88 | 
             
              end
         | 
| 55 89 |  | 
| 56 90 | 
             
              it "should define only a default original variant if no other variants are given" do
         | 
| @@ -63,7 +97,7 @@ describe "AttachmentSan::Has, concerning a single associated attachment" do | |
| 63 97 | 
             
                %w{ original header }.each do |name|
         | 
| 64 98 | 
             
                  variant = @document.logo.send(name)
         | 
| 65 99 | 
             
                  variant.name.to_s.should == name
         | 
| 66 | 
            -
                  variant.should.be.instance_of Logo.reflect_on_variant(name)[:class]
         | 
| 100 | 
            +
                  variant.should.be.instance_of Document::Logo.reflect_on_variant(name)[:class]
         | 
| 67 101 | 
             
                end
         | 
| 68 102 | 
             
              end
         | 
| 69 103 | 
             
            end
         | 
| @@ -75,10 +109,8 @@ describe "AttachmentSan::Has, concerning a collection of associated attachments" | |
| 75 109 | 
             
                2.times { @document.misc_files.build :uploaded_file => rails_icon }
         | 
| 76 110 | 
             
              end
         | 
| 77 111 |  | 
| 78 | 
            -
              it "should  | 
| 79 | 
            -
                 | 
| 80 | 
            -
                reflection.macro.should == :has_many
         | 
| 81 | 
            -
                reflection.klass.should == Image
         | 
| 112 | 
            +
              it "should define a has_many association" do
         | 
| 113 | 
            +
                Document.reflect_on_association(:images).macro.should == :has_many
         | 
| 82 114 | 
             
              end
         | 
| 83 115 |  | 
| 84 116 | 
             
              it "should define only a default original variant if no others are given" do
         | 
| @@ -98,19 +130,17 @@ end | |
| 98 130 |  | 
| 99 131 | 
             
            describe "AttachmentSan::Has, concerning attachment definitions with only a default original variant" do
         | 
| 100 132 | 
             
              it "should pass the options hash on to the variant" do
         | 
| 101 | 
            -
                MiscFile.variant_reflections.length.should == 1
         | 
| 102 | 
            -
                MiscFile.variant_reflections.first[:name].should == :original
         | 
| 103 | 
            -
                MiscFile.variant_reflections.first[:class].should ==  | 
| 104 | 
            -
                MiscFile.variant_reflections.first[:filename_scheme].should == :keep_original
         | 
| 105 | 
            -
                MiscFile.variant_reflections.first[:process].call.should == :from_process_proc
         | 
| 133 | 
            +
                Document::MiscFile.variant_reflections.length.should == 1
         | 
| 134 | 
            +
                Document::MiscFile.variant_reflections.first[:name].should == :original
         | 
| 135 | 
            +
                Document::MiscFile.variant_reflections.first[:class].should == MyOriginal
         | 
| 136 | 
            +
                # Document::MiscFile.variant_reflections.first[:filename_scheme].should == :keep_original
         | 
| 137 | 
            +
                Document::MiscFile.variant_reflections.first[:process].call.should == :from_process_proc
         | 
| 106 138 | 
             
              end
         | 
| 107 139 | 
             
            end
         | 
| 108 140 |  | 
| 109 | 
            -
            describe "AttachmentSan::Has, concerning attachment definitions  | 
| 110 | 
            -
              it "should  | 
| 111 | 
            -
                 | 
| 112 | 
            -
                 | 
| 113 | 
            -
                card.small_card.should.be.instance_of AddressCard::SmallCard
         | 
| 114 | 
            -
                card.big_card.should.be.instance_of AddressCard::BigCard
         | 
| 141 | 
            +
            describe "AttachmentSan::Has, concerning attachment definitions overriding attachment base class options" do
         | 
| 142 | 
            +
              it "should merge the options onto the attachment_san_options of the attachment model subclass" do
         | 
| 143 | 
            +
                OtherDocument::Image.attachment_san_options[:base_path].should == '/other/base'
         | 
| 144 | 
            +
                OtherDocument::Image.attachment_san_options[:public_base_path].should == '/other/public'
         | 
| 115 145 | 
             
              end
         | 
| 116 146 | 
             
            end
         | 
    
        data/test/lib/schema.rb
    CHANGED
    
    | @@ -1,6 +1,5 @@ | |
| 1 1 | 
             
            ActiveRecord::Migration.verbose = false
         | 
| 2 2 | 
             
            ActiveRecord::Schema.define(:version => 1) do
         | 
| 3 | 
            -
             | 
| 4 3 | 
             
              create_table :attachments, :force => true do |t|
         | 
| 5 4 | 
             
                t.string  :filename
         | 
| 6 5 | 
             
                t.string  :content_type
         | 
| @@ -10,5 +9,7 @@ ActiveRecord::Schema.define(:version => 1) do | |
| 10 9 |  | 
| 11 10 | 
             
              create_table :documents, :force => true do |t|
         | 
| 12 11 | 
             
              end
         | 
| 13 | 
            -
             | 
| 12 | 
            +
              
         | 
| 13 | 
            +
              create_table :other_documents, :force => true do |t|
         | 
| 14 | 
            +
              end
         | 
| 14 15 | 
             
            end
         | 
    
        data/test/variant_test.rb
    CHANGED
    
    | @@ -2,19 +2,19 @@ require File.expand_path('../test_helper', __FILE__) | |
| 2 2 |  | 
| 3 3 | 
             
            describe "AttachmentSan's variant class methods" do
         | 
| 4 4 | 
             
              it "should return the variant class to use" do
         | 
| 5 | 
            -
                reflection = Logo.reflect_on_variant(:header)
         | 
| 5 | 
            +
                reflection = Document::Logo.reflect_on_variant(:header)
         | 
| 6 6 | 
             
                reflection[:class].should.be MyVariant
         | 
| 7 7 | 
             
              end
         | 
| 8 8 |  | 
| 9 9 | 
             
              it "should by default use the AttachmentSan::Variant class" do
         | 
| 10 | 
            -
                reflection = Image.reflect_on_variant(:thumbnail)
         | 
| 10 | 
            +
                reflection = Document::Image.reflect_on_variant(:thumbnail)
         | 
| 11 11 | 
             
                reflection[:class].should.be AttachmentSan::Variant
         | 
| 12 12 | 
             
              end
         | 
| 13 13 |  | 
| 14 14 | 
             
              it "should not define a variant twice" do
         | 
| 15 | 
            -
                count_before = Logo.variant_reflections.length
         | 
| 15 | 
            +
                count_before = Document::Logo.variant_reflections.length
         | 
| 16 16 | 
             
                Document.has_attachment :logo, :variants => { :header => MyVariant }
         | 
| 17 | 
            -
                Logo.variant_reflections.length.should == count_before
         | 
| 17 | 
            +
                Document::Logo.variant_reflections.length.should == count_before
         | 
| 18 18 | 
             
              end
         | 
| 19 19 | 
             
            end
         | 
| 20 20 |  | 
| @@ -51,17 +51,28 @@ describe "A AttachmentSan::Variant instance in general" do | |
| 51 51 | 
             
              end
         | 
| 52 52 |  | 
| 53 53 | 
             
              it "should return the extension of the original file" do
         | 
| 54 | 
            -
                Image.attachment_san_options[:extension] = :keep_original
         | 
| 54 | 
            +
                Document::Image.attachment_san_options[:extension] = :keep_original
         | 
| 55 55 | 
             
                @thumbnail.extension.should == 'png'
         | 
| 56 56 | 
             
              end
         | 
| 57 57 |  | 
| 58 58 | 
             
              it "should use the extension specified in the attachment_san_options" do
         | 
| 59 | 
            -
                Image.attachment_san_options[:extension] = :jpeg
         | 
| 59 | 
            +
                Document::Image.attachment_san_options[:extension] = :jpeg
         | 
| 60 60 | 
             
                @thumbnail.extension.should == :jpeg
         | 
| 61 61 | 
             
              end
         | 
| 62 62 |  | 
| 63 | 
            +
              it "should should use the base_path and public_base_path that were overridden on the has_attachment(s) definition" do
         | 
| 64 | 
            +
                @document = OtherDocument.new
         | 
| 65 | 
            +
                @image = @document.images.build(:uploaded_file => @upload)
         | 
| 66 | 
            +
                
         | 
| 67 | 
            +
                @image.original.base_path.should == '/other/base'
         | 
| 68 | 
            +
                @image.original.public_base_path.should == '/other/public'
         | 
| 69 | 
            +
                
         | 
| 70 | 
            +
                @image.normal.base_path.should == '/yet/another/base'
         | 
| 71 | 
            +
                @image.normal.public_base_path.should == '/other/public'
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
              
         | 
| 63 74 | 
             
              it "should create the directory that the file_path returns" do
         | 
| 64 | 
            -
                Image.attachment_san_options[:filename_scheme] = :record_identifier
         | 
| 75 | 
            +
                Document::Image.attachment_san_options[:filename_scheme] = :record_identifier
         | 
| 65 76 |  | 
| 66 77 | 
             
                @thumbnail.dir_path.should == File.dirname(@thumbnail.file_path)
         | 
| 67 78 | 
             
                File.should.not.exist @thumbnail.dir_path
         | 
| @@ -79,8 +90,8 @@ describe "A AttachmentSan::Variant instance in general" do | |
| 79 90 |  | 
| 80 91 | 
             
              { :keep_original => 'png', :jpg => 'jpg' }.each do |setting, ext|
         | 
| 81 92 | 
             
                it "should return a filename named after the variant name plus #{setting}" do
         | 
| 82 | 
            -
                  Image.attachment_san_options[:filename_scheme] = :variant_name
         | 
| 83 | 
            -
                  Image.attachment_san_options[:extension] = setting
         | 
| 93 | 
            +
                  Document::Image.attachment_san_options[:filename_scheme] = :variant_name
         | 
| 94 | 
            +
                  Document::Image.attachment_san_options[:extension] = setting
         | 
| 84 95 |  | 
| 85 96 | 
             
                  @thumbnail.filename.should == "thumbnail.#{ext}"
         | 
| 86 97 | 
             
                  @thumbnail.file_path.should == File.join(@thumbnail.base_path, "thumbnail.#{ext}")
         | 
| @@ -91,9 +102,22 @@ describe "A AttachmentSan::Variant instance in general" do | |
| 91 102 | 
             
                  @medium_sized.public_path.should == File.join(@thumbnail.public_base_path, "medium_sized.#{ext}")
         | 
| 92 103 | 
             
                end
         | 
| 93 104 |  | 
| 105 | 
            +
                it "should return the original filename and use extension #{setting}" do
         | 
| 106 | 
            +
                  Document::Image.attachment_san_options[:filename_scheme] = :keep_original
         | 
| 107 | 
            +
                  Document::Image.attachment_san_options[:extension] = setting
         | 
| 108 | 
            +
                  
         | 
| 109 | 
            +
                  @image.original.filename.should == "rails.png"
         | 
| 110 | 
            +
                  @image.original.file_path.should == File.join(@thumbnail.base_path, "rails.png")
         | 
| 111 | 
            +
                  @image.original.public_path.should == File.join(@thumbnail.public_base_path, "rails.png")
         | 
| 112 | 
            +
                  
         | 
| 113 | 
            +
                  @thumbnail.filename.should == "rails.thumbnail.#{ext}"
         | 
| 114 | 
            +
                  @thumbnail.file_path.should == File.join(@thumbnail.base_path, "rails.thumbnail.#{ext}")
         | 
| 115 | 
            +
                  @thumbnail.public_path.should == File.join(@thumbnail.public_base_path, "rails.thumbnail.#{ext}")
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
                
         | 
| 94 118 | 
             
                it "should return a filename which should be a random token from the record and append #{setting}" do
         | 
| 95 | 
            -
                  Image.attachment_san_options[:filename_scheme] = :token
         | 
| 96 | 
            -
                  Image.attachment_san_options[:extension] = setting
         | 
| 119 | 
            +
                  Document::Image.attachment_san_options[:filename_scheme] = :token
         | 
| 120 | 
            +
                  Document::Image.attachment_san_options[:extension] = setting
         | 
| 97 121 | 
             
                  @image.stubs(:token).returns('556d2e8e')
         | 
| 98 122 |  | 
| 99 123 | 
             
                  @image.original.filename.should == "55/6d/2e/8e/rails.png"
         | 
| @@ -108,8 +132,8 @@ describe "A AttachmentSan::Variant instance in general" do | |
| 108 132 | 
             
                it "should return a filename which is based on the record identifier and variant name plus #{setting}" do
         | 
| 109 133 | 
             
                  Attachment.reset!
         | 
| 110 134 |  | 
| 111 | 
            -
                  Image.attachment_san_options[:extension] = setting
         | 
| 112 | 
            -
                  Image.attachment_san_options[:filename_scheme] = :record_identifier
         | 
| 135 | 
            +
                  Document::Image.attachment_san_options[:extension] = setting
         | 
| 136 | 
            +
                  Document::Image.attachment_san_options[:filename_scheme] = :record_identifier
         | 
| 113 137 | 
             
                  @image.save!
         | 
| 114 138 |  | 
| 115 139 | 
             
                  @thumbnail.filename.should == "/images/#{@image.id}/thumbnail.#{ext}"
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: attachment-san
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - Eloy Duran
         | 
| @@ -10,7 +10,7 @@ autorequire: | |
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 12 |  | 
| 13 | 
            -
            date: 2009- | 
| 13 | 
            +
            date: 2009-12-01 00:00:00 +01:00
         | 
| 14 14 | 
             
            default_executable: 
         | 
| 15 15 | 
             
            dependencies: []
         | 
| 16 16 |  | 
| @@ -36,6 +36,7 @@ files: | |
| 36 36 | 
             
            - examples/photos_controller.rb
         | 
| 37 37 | 
             
            - examples/post.rb
         | 
| 38 38 | 
             
            - lib/attachment_san.rb
         | 
| 39 | 
            +
            - lib/attachment_san/core_ext.rb
         | 
| 39 40 | 
             
            - lib/attachment_san/has.rb
         | 
| 40 41 | 
             
            - lib/attachment_san/test/helper.rb
         | 
| 41 42 | 
             
            - lib/attachment_san/test/rails.png
         | 
| @@ -43,6 +44,7 @@ files: | |
| 43 44 | 
             
            - napkin.rb
         | 
| 44 45 | 
             
            - rails/init.rb
         | 
| 45 46 | 
             
            - test/attachment_san_test.rb
         | 
| 47 | 
            +
            - test/core_ext_test.rb
         | 
| 46 48 | 
             
            - test/fixtures/models/attachment.rb
         | 
| 47 49 | 
             
            - test/fixtures/models/document.rb
         | 
| 48 50 | 
             
            - test/fixtures/models/options_stub.rb
         | 
| @@ -80,6 +82,7 @@ specification_version: 3 | |
| 80 82 | 
             
            summary: Rails plugin for easy and rich attachment manipulation.
         | 
| 81 83 | 
             
            test_files: 
         | 
| 82 84 | 
             
            - test/attachment_san_test.rb
         | 
| 85 | 
            +
            - test/core_ext_test.rb
         | 
| 83 86 | 
             
            - test/fixtures/models/attachment.rb
         | 
| 84 87 | 
             
            - test/fixtures/models/document.rb
         | 
| 85 88 | 
             
            - test/fixtures/models/options_stub.rb
         |