nifty-attachments 1.0.0

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.
@@ -0,0 +1,4 @@
1
+ require 'securerandom'
2
+ require 'digest/md5'
3
+ require 'nifty/attachments/version'
4
+ require 'nifty/attachments/railtie' if defined?(Rails)
@@ -0,0 +1,53 @@
1
+ module Nifty
2
+ module Attachments
3
+ class Attachment < ActiveRecord::Base
4
+
5
+ # Set the table name
6
+ self.table_name = 'nifty_attachments'
7
+
8
+ # This will be the ActionDispatch::UploadedFile object which be diseminated
9
+ # by the class on save.
10
+ attr_accessor :uploaded_file
11
+
12
+ # Relationships
13
+ belongs_to :parent, :polymorphic => true
14
+
15
+ # Validations
16
+ validates :file_name, :presence => true
17
+ validates :file_type, :presence => true
18
+ validates :data, :presence => true
19
+ validates :digest, :presence => true
20
+ validates :token, :presence => true, :uniqueness => true
21
+
22
+ # All attachments should have a token assigned to this
23
+ before_validation { self.token = SecureRandom.uuid if self.token.blank? }
24
+
25
+ # Copy values from the `uploaded_file` and set them as the appropriate
26
+ # fields on this model
27
+ before_validation do
28
+ if self.uploaded_file
29
+ self.data = self.uploaded_file.tempfile.read
30
+ self.file_name = self.uploaded_file.original_filename
31
+ self.file_type = self.uploaded_file.content_type
32
+ self.digest = Digest::MD5.hexdigest(self.data)
33
+ end
34
+ end
35
+
36
+ # Return the attachment for a given role
37
+ def self.for(role)
38
+ self.where(:role => role).first
39
+ end
40
+
41
+ # Return the path to the attachment
42
+ def path
43
+ "/attachment/#{token}/#{file_name}"
44
+ end
45
+
46
+ # Is the attachment an image?
47
+ def image?
48
+ file_type =~ /\Aimage\//
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,29 @@
1
+ module Nifty
2
+ module Attachments
3
+ class Middleware
4
+
5
+ def initialize(app)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ if env['PATH_INFO'] =~ /\A\/attachment\/([a-f0-9\-]{36})\/(.*)/
11
+ if attachment = Nifty::Attachments::Attachment.find_by_token($1)
12
+ [200, {
13
+ 'Content-Length' => attachment.data.bytesize.to_s,
14
+ 'Content-Type' => attachment.file_type,
15
+ 'Cache-Control' => "public, maxage=#{1.year.to_i}",
16
+ 'Content-Disposition' => "attachment; filename=\"#{attachment.file_name}\""
17
+ },
18
+ [attachment.data]]
19
+ else
20
+ [404, {}, ["Attachment not found"]]
21
+ end
22
+ else
23
+ @app.call(env)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ class CreateNiftyAttachmentsTable < ActiveRecord::Migration
2
+
3
+ def up
4
+ create_table :nifty_attachments do |t|
5
+ t.integer :parent_id
6
+ t.string :parent_type, :token, :digest, :role, :file_name, :file_type
7
+ t.binary :data, :limit => 10.megabytes
8
+ t.timestamps
9
+ end
10
+ end
11
+
12
+ def down
13
+ drop_table :nifty_attachments
14
+ end
15
+
16
+ end
@@ -0,0 +1,21 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module Nifty
5
+ module Attachments
6
+ class MigrationGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+
9
+ source_root File.expand_path("../", __FILE__)
10
+
11
+ def self.next_migration_number(path)
12
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
13
+ end
14
+
15
+ def create_model_file
16
+ migration_template 'migration.rb', "db/migrate/create_nifty_attachments_table"
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,47 @@
1
+ module Nifty
2
+ module Attachments
3
+ module ModelExtension
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ base.before_save do
8
+ if @pending_attachments
9
+ @pending_attachments.each do |pa|
10
+ old_attachments = self.nifty_attachments.where(:role => pa[:role]).pluck(:id)
11
+ self.nifty_attachments.create(:uploaded_file => pa[:file], :role => pa[:role])
12
+ self.nifty_attachments.where(:id => old_attachments).destroy_all
13
+ end
14
+ @pending_attachments = nil
15
+ end
16
+ end
17
+ end
18
+
19
+ module ClassMethods
20
+
21
+ def attachment(name)
22
+ unless self.reflect_on_all_associations(:has_many).map(&:name).include?(:nifty_attachments)
23
+ has_many :nifty_attachments, :as => :parent, :dependent => :destroy, :class_name => 'Nifty::Attachments::Attachment'
24
+ end
25
+
26
+ has_one name, -> { select(:id, :token, :digest, :parent_id, :parent_type, :file_name, :file_type).where(:role => name) }, :class_name => 'Nifty::Attachments::Attachment', :as => :parent
27
+
28
+ define_method "#{name}_file" do
29
+ instance_variable_get("@#{name}_file")
30
+ end
31
+
32
+ define_method "#{name}_file=" do |file|
33
+ instance_variable_set("@#{name}_file", file)
34
+ if file.is_a?(ActionDispatch::Http::UploadedFile)
35
+ @pending_attachments ||= []
36
+ @pending_attachments << {:role => name, :file => file}
37
+ else
38
+ nil
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ module Nifty
2
+ module Attachments
3
+ class Railtie < Rails::Railtie #:nodoc:
4
+
5
+ initializer 'nifty.attachments.initialize' do |app|
6
+
7
+ require 'nifty/attachments/middleware'
8
+ app.config.middleware.use Nifty::Attachments::Middleware
9
+
10
+ ActiveSupport.on_load(:active_record) do
11
+ require 'nifty/attachments/attachment'
12
+ require 'nifty/attachments/model_extension'
13
+ ::ActiveRecord::Base.send :include, Nifty::Attachments::ModelExtension
14
+ end
15
+
16
+ end
17
+
18
+ generators do
19
+ require 'nifty/attachments/migration_generator'
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,5 @@
1
+ module Nifty
2
+ module Attachments
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nifty-attachments
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Adam Cooke
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-07 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Attach documents & files to Active Record models
15
+ email:
16
+ - adam@niftyware.io
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/nifty/attachments/attachment.rb
22
+ - lib/nifty/attachments/middleware.rb
23
+ - lib/nifty/attachments/migration.rb
24
+ - lib/nifty/attachments/migration_generator.rb
25
+ - lib/nifty/attachments/model_extension.rb
26
+ - lib/nifty/attachments/railtie.rb
27
+ - lib/nifty/attachments/version.rb
28
+ - lib/nifty/attachments.rb
29
+ homepage: https://github.com/niftyware/attachments
30
+ licenses: []
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 1.8.23
50
+ signing_key:
51
+ specification_version: 3
52
+ summary: Attach documents & files to Active Record models
53
+ test_files: []