attachs 0.4.5 → 4.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +83 -218
  4. data/Rakefile +1 -14
  5. data/lib/attachs.rb +98 -31
  6. data/lib/attachs/attachment.rb +301 -72
  7. data/lib/attachs/builder.rb +78 -0
  8. data/lib/attachs/collection.rb +84 -0
  9. data/lib/attachs/concern.rb +47 -0
  10. data/lib/attachs/configuration.rb +11 -0
  11. data/lib/attachs/console.rb +40 -0
  12. data/lib/attachs/extensions/active_record/base.rb +24 -0
  13. data/lib/attachs/extensions/active_record/validations/attachment_content_type_validator.rb +37 -0
  14. data/lib/attachs/extensions/active_record/validations/attachment_presence_validator.rb +27 -0
  15. data/lib/attachs/extensions/active_record/validations/attachment_size_validator.rb +55 -0
  16. data/lib/attachs/extensions/active_record/validations/attachment_validator.rb +24 -0
  17. data/lib/attachs/interpolations.rb +27 -0
  18. data/lib/attachs/jobs/base.rb +14 -0
  19. data/lib/attachs/jobs/delete_job.rb +15 -0
  20. data/lib/attachs/jobs/update_job.rb +11 -0
  21. data/lib/attachs/locales/en.yml +2 -6
  22. data/lib/attachs/locales/es.yml +2 -6
  23. data/lib/attachs/processors/base.rb +4 -14
  24. data/lib/attachs/processors/image.rb +45 -0
  25. data/lib/attachs/railtie.rb +7 -27
  26. data/lib/attachs/storages/base.rb +10 -59
  27. data/lib/attachs/storages/s3.rb +68 -63
  28. data/lib/attachs/version.rb +1 -1
  29. data/lib/generators/attachs/install/install_generator.rb +15 -0
  30. data/lib/generators/attachs/install/templates/initializer.rb +7 -0
  31. data/lib/generators/attachs/upload/templates/migration.rb +11 -0
  32. data/lib/generators/attachs/upload/templates/model.rb +19 -0
  33. data/lib/generators/attachs/upload/upload_generator.rb +24 -0
  34. data/lib/tasks/attachs.rake +12 -26
  35. data/test/attachment_test.rb +175 -12
  36. data/test/collection_test.rb +52 -0
  37. data/test/concern_test.rb +10 -0
  38. data/test/dummy/Rakefile +1 -2
  39. data/test/dummy/app/assets/javascripts/application.js +2 -2
  40. data/test/dummy/app/assets/stylesheets/application.css +6 -4
  41. data/test/dummy/app/models/product.rb +16 -0
  42. data/test/dummy/app/models/shop.rb +14 -0
  43. data/test/dummy/app/models/upload.rb +19 -0
  44. data/test/dummy/app/views/layouts/application.html.erb +9 -11
  45. data/test/dummy/bin/bundle +1 -0
  46. data/test/dummy/bin/rails +2 -1
  47. data/test/dummy/bin/rake +1 -0
  48. data/test/dummy/bin/setup +30 -0
  49. data/test/dummy/config.ru +1 -1
  50. data/test/dummy/config/application.rb +3 -2
  51. data/test/dummy/config/boot.rb +1 -1
  52. data/test/dummy/config/database.yml +4 -22
  53. data/test/dummy/config/database.yml.travis +3 -0
  54. data/test/dummy/config/environment.rb +1 -1
  55. data/test/dummy/config/environments/development.rb +15 -3
  56. data/test/dummy/config/environments/production.rb +21 -26
  57. data/test/dummy/config/environments/test.rb +10 -12
  58. data/test/dummy/config/initializers/assets.rb +11 -0
  59. data/test/dummy/config/initializers/attachs.rb +7 -21
  60. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  61. data/test/dummy/config/initializers/mime_types.rb +1 -2
  62. data/test/dummy/config/initializers/session_store.rb +1 -1
  63. data/test/dummy/config/routes.rb +54 -0
  64. data/test/dummy/config/secrets.yml +24 -0
  65. data/test/dummy/db/migrate/20161024234003_create_shops.rb +11 -0
  66. data/test/dummy/db/migrate/20161024234029_create_products.rb +12 -0
  67. data/test/dummy/db/migrate/20161031135453_create_uploads.rb +11 -0
  68. data/test/dummy/db/schema.rb +27 -16
  69. data/test/dummy/log/development.log +61 -0
  70. data/test/dummy/log/test.log +5873 -0
  71. data/test/dummy/public/404.html +58 -55
  72. data/test/dummy/public/422.html +58 -55
  73. data/test/dummy/public/500.html +57 -54
  74. data/test/fixtures/big_file.txt +50 -0
  75. data/test/fixtures/big_image.jpg +0 -0
  76. data/test/fixtures/file.txt +1 -0
  77. data/test/fixtures/image.jpg +0 -0
  78. data/test/{dummy/test/fixtures/file.txt → fixtures/small_file.txt} +0 -0
  79. data/test/fixtures/small_image.jpg +0 -0
  80. data/test/generator_test.rb +14 -6
  81. data/test/helper_test.rb +28 -0
  82. data/test/query_test.rb +26 -0
  83. data/test/support/storage_helper.rb +65 -0
  84. data/test/task_test.rb +69 -0
  85. data/test/test_helper.rb +6 -45
  86. data/test/upload_test.rb +27 -0
  87. data/test/validator_test.rb +160 -0
  88. metadata +114 -68
  89. data/lib/attachs/active_record/base.rb +0 -103
  90. data/lib/attachs/active_record/connection_adapters.rb +0 -40
  91. data/lib/attachs/active_record/migration.rb +0 -17
  92. data/lib/attachs/active_record/validators.rb +0 -7
  93. data/lib/attachs/active_record/validators/attachment_content_type_validator.rb +0 -30
  94. data/lib/attachs/active_record/validators/attachment_presence_validator.rb +0 -22
  95. data/lib/attachs/active_record/validators/attachment_size_validator.rb +0 -47
  96. data/lib/attachs/processors/thumbnail.rb +0 -69
  97. data/lib/attachs/storages/local.rb +0 -95
  98. data/lib/attachs/types/base.rb +0 -22
  99. data/lib/attachs/types/default.rb +0 -29
  100. data/lib/attachs/types/regular.rb +0 -21
  101. data/lib/generators/attachs/install_generator.rb +0 -13
  102. data/lib/generators/attachs/templates/attachs.rb +0 -2
  103. data/test/dummy/README.rdoc +0 -28
  104. data/test/dummy/app/models/medium.rb +0 -5
  105. data/test/dummy/app/models/picture.rb +0 -2
  106. data/test/dummy/config/initializers/secret_token.rb +0 -13
  107. data/test/dummy/config/s3.yml +0 -15
  108. data/test/dummy/db/migrate/20140808012639_create_media.rb +0 -11
  109. data/test/dummy/test/fixtures/image.gif +0 -0
  110. data/test/local_storage_test.rb +0 -72
  111. data/test/migration_test.rb +0 -65
  112. data/test/processor_test.rb +0 -49
  113. data/test/s3_storage_tes.rb +0 -66
  114. data/test/tasks_test.rb +0 -57
  115. data/test/validators_test.rb +0 -100
@@ -1,103 +0,0 @@
1
- module Attachs
2
- module ActiveRecord
3
- module Base
4
- extend ActiveSupport::Concern
5
-
6
- protected
7
-
8
- def attachments
9
- @attachments ||= {}.tap do |instances|
10
- self.class.attachments.each do |attr, options|
11
- instances[attr] = Attachs::Attachment.new(self, attr, options)
12
- end
13
- end
14
- end
15
-
16
- def queued_attachments
17
- @queued_attachments ||= { process: {}, destroy: {} }
18
- end
19
-
20
- def queue_attachment(attr, options, value)
21
- unless queued_attachments[:destroy].has_key? attr
22
- queued_attachments[:destroy][attr] = attachments[attr]
23
- end
24
- if queued_attachments[:process].has_key? attr and value.nil?
25
- attachments[attr]
26
- else
27
- queued_attachments[:process][attr] = Attachs::Attachment.new(self, attr, options, value)
28
- end
29
- end
30
-
31
- def commit_attachments
32
- self.class.attachments.each do |attr, options|
33
- send "destroy_#{attr}=", nil
34
- end
35
- queued_attachments[:destroy].each do |attr, attachment|
36
- attachment.destroy
37
- end
38
- queued_attachments[:process].each do |attr, attachment|
39
- attachment.process
40
- end
41
- queued_attachments[:destroy] = {}
42
- queued_attachments[:process] = {}
43
- end
44
-
45
- def destroy_attachments
46
- self.class.attachments.each do |attr, options|
47
- send(attr).destroy
48
- end
49
- end
50
-
51
- module ClassMethods
52
-
53
- def has_attached_file(*args)
54
- options = args.extract_options!
55
- unless attachable?
56
- make_attachable
57
- end
58
- args.each do |attr|
59
- define_attachment_methods attr, options
60
- attachments[attr] = options
61
- end
62
- end
63
-
64
- def attachments
65
- @attachments ||= {}
66
- end
67
-
68
- def attachable?
69
- attachments.any?
70
- end
71
-
72
- def inherited(subclass)
73
- subclass.instance_variable_set :@attachments, @attachments
74
- super
75
- end
76
-
77
- protected
78
-
79
- def make_attachable
80
- after_save :commit_attachments
81
- after_destroy :destroy_attachments
82
- end
83
-
84
- def define_attachment_methods(attr, options)
85
- define_method "#{attr}=" do |value|
86
- attachments[attr] = queue_attachment(attr, options, value)
87
- end
88
- define_method attr do
89
- attachments[attr]
90
- end
91
- attr_reader "destroy_#{attr}"
92
- define_method "destroy_#{attr}=" do |value|
93
- instance_variable_set "@destroy_#{attr}", value
94
- if [1, '1', true].include?(value) and !send(attr).upload?
95
- send "#{attr}=", nil
96
- end
97
- end
98
- end
99
-
100
- end
101
- end
102
- end
103
- end
@@ -1,40 +0,0 @@
1
- module Attachs
2
- module ActiveRecord
3
- module ConnectionAdapters
4
- COLUMNS = {
5
- filename: 'string',
6
- content_type: 'string',
7
- size: 'integer',
8
- updated_at: 'datetime'
9
- }
10
-
11
- module AbstractAdapter
12
- def add_attachment(table_name, *attachment_names)
13
- attachment_names.each do |attachment_name|
14
- COLUMNS.each do |column_name, column_type|
15
- add_column table_name, "#{attachment_name}_#{column_name}", column_type
16
- end
17
- end
18
- end
19
-
20
- def remove_attachment(table_name, *attachment_names)
21
- attachment_names.each do |attachment_name|
22
- COLUMNS.each do |column_name, column_type|
23
- remove_column table_name, "#{attachment_name}_#{column_name}"
24
- end
25
- end
26
- end
27
- end
28
-
29
- module TableDefinition
30
- def attachment(*attachment_names)
31
- attachment_names.each do |attachment_name|
32
- COLUMNS.each do |column_name, column_type|
33
- column "#{attachment_name}_#{column_name}", column_type
34
- end
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,17 +0,0 @@
1
- module Attachs
2
- module ActiveRecord
3
- module Migration
4
- module CommandRecorder
5
- def add_attachment(*args)
6
- record :add_attachment, args
7
- end
8
-
9
- private
10
-
11
- def invert_add_attachment(*args)
12
- [:remove_attachment, args]
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,7 +0,0 @@
1
- module Attachs
2
- module ActiveRecord
3
- module Validators
4
- extend ActiveSupport::Concern
5
- end
6
- end
7
- end
@@ -1,30 +0,0 @@
1
- module Attachs
2
- module ActiveRecord
3
- module Validators
4
- class AttachmentContentTypeValidator < ActiveModel::EachValidator
5
-
6
- def validate_each(record, attribute, value)
7
- if value.exists?
8
- if options.has_key? :with
9
- if options[:with] !~ value.content_type
10
- record.errors.add attribute, :attachment_content_type_with
11
- end
12
- elsif options.has_key? :in
13
- if options[:in].exclude? value.content_type
14
- record.errors.add attribute, :attachment_content_type_in, types: options[:in].to_sentence
15
- end
16
- end
17
- end
18
- end
19
-
20
- end
21
- module ClassMethods
22
-
23
- def validates_attachment_content_type_of(*attr_names)
24
- validates_with AttachmentContentTypeValidator, _merge_attributes(attr_names)
25
- end
26
-
27
- end
28
- end
29
- end
30
- end
@@ -1,22 +0,0 @@
1
- module Attachs
2
- module ActiveRecord
3
- module Validators
4
- class AttachmentPresenceValidator < ActiveModel::EachValidator
5
-
6
- def validate_each(record, attribute, value)
7
- if value.blank?
8
- record.errors.add attribute, :attachment_presence
9
- end
10
- end
11
-
12
- end
13
- module ClassMethods
14
-
15
- def validates_attachment_presence_of(*attr_names)
16
- validates_with AttachmentPresenceValidator, _merge_attributes(attr_names)
17
- end
18
-
19
- end
20
- end
21
- end
22
- end
@@ -1,47 +0,0 @@
1
- module Attachs
2
- module ActiveRecord
3
- module Validators
4
- class AttachmentSizeValidator < ActiveModel::EachValidator
5
- include ActionView::Helpers::NumberHelper
6
-
7
- def validate_each(record, attribute, value)
8
- if value.exists?
9
- if options.has_key? :in
10
- if options[:in].exclude? value.size
11
- record.errors.add(
12
- attribute,
13
- :attachment_size_in,
14
- min: number_to_human_size(options[:in].begin),
15
- max: number_to_human_size(options[:in].end)
16
- )
17
- end
18
- else
19
- if options.has_key? :less_than and value.size > options[:less_than]
20
- record.errors.add(
21
- attribute,
22
- :attachment_size_less_than,
23
- count: number_to_human_size(options[:less_than])
24
- )
25
- end
26
- if options.has_key? :greater_than and value.size < options[:greater_than]
27
- record.errors.add(
28
- attribute,
29
- :attachment_size_greater_than,
30
- count: number_to_human_size(options[:greater_than])
31
- )
32
- end
33
- end
34
- end
35
- end
36
-
37
- end
38
- module ClassMethods
39
-
40
- def validates_attachment_size_of(*attr_names)
41
- validates_with AttachmentSizeValidator, _merge_attributes(attr_names)
42
- end
43
-
44
- end
45
- end
46
- end
47
- end
@@ -1,69 +0,0 @@
1
- module Attachs
2
- module Processors
3
- class Thumbnail < Base
4
-
5
- def initialize(attachment, source)
6
- super
7
- @width, @height = dimensions(source)
8
- end
9
-
10
- def process(style, destination)
11
- new_width, new_height, strategy, options = geometry(style)
12
- resize source, width, height, new_width, new_height, strategy, options, destination
13
- end
14
-
15
- protected
16
-
17
- attr_reader :width, :height
18
-
19
- def geometry(style)
20
- geometry = Attachs.config.styles[style]
21
- width, height = geometry.scan(/[^x]+/).map(&:to_i)
22
- case geometry[/!|#/]
23
- when '#'
24
- strategy = 'cover'
25
- when '!'
26
- strategy = 'force'
27
- else
28
- strategy = 'contain'
29
- end
30
- options = Attachs.config.convert_options[style]
31
- [width, height, strategy, options]
32
- end
33
-
34
- def resize(source, width, height, new_width, new_height, strategy, custom_options, destination)
35
- case strategy
36
- when 'cover'
37
- ratio = [new_width.to_f/width, new_height.to_f/height].max
38
- options = "-resize #{(ratio*width).ceil}x#{(ratio*height).ceil} -gravity center -crop #{new_width}x#{new_height}+0+0"
39
- when 'force'
40
- options = "-resize #{new_width}x#{new_height}\!"
41
- when 'contain'
42
- options = "-resize #{new_width}x#{new_height}"
43
- end
44
- if global_options = Attachs.config.global_convert_options
45
- options << " #{global_options}"
46
- end
47
- if custom_options
48
- options << " #{custom_options}"
49
- end
50
- convert source, options, destination
51
- end
52
-
53
- def dimensions(source)
54
- if output = identify(source, '-format %wx%h')
55
- output.split('x').map(&:to_i)
56
- end
57
- end
58
-
59
- def convert(source, options, destination)
60
- run "convert '#{source}' #{options} '#{destination}'"
61
- end
62
-
63
- def identify(source, options)
64
- run "identify #{options} '#{source}'"
65
- end
66
-
67
- end
68
- end
69
- end
@@ -1,95 +0,0 @@
1
- module Attachs
2
- module Storages
3
- class Local < Base
4
-
5
- def url(*args)
6
- if attachment.url?
7
- options = args.extract_options!
8
- style = (args[0] || :original)
9
- base_url.join(path(style)).to_s.tap do |url|
10
- if find_option(options, :cachebuster, Attachs.config.cachebuster)
11
- url << "?#{attachment.updated_at.to_i}"
12
- end
13
- end
14
- end
15
- end
16
-
17
- def process(force=false)
18
- if attachment.upload?
19
- FileUtils.mkdir_p realpath.dirname
20
- attachment.upload.rewind
21
- File.open(realpath, 'wb') do |file|
22
- while chunk = attachment.upload.read(16 * 1024)
23
- file.write chunk
24
- end
25
- end
26
- attachment.uploaded!
27
- end
28
- process_styles force
29
- end
30
-
31
- def process_styles(force=false)
32
- if attachment.image?
33
- attachment.processors.each do |klass|
34
- processor = klass.new(attachment, realpath)
35
- attachment.styles.each do |style|
36
- if force == true
37
- delete realpath(style)
38
- end
39
- unless File.exist? realpath(style)
40
- FileUtils.mkdir_p realpath(style).dirname
41
- processor.process style, realpath(style)
42
- end
43
- end
44
- end
45
- end
46
- end
47
-
48
- def destroy
49
- delete realpath
50
- destroy_styles
51
- end
52
-
53
- def destroy_styles
54
- if attachment.image?
55
- attachment.styles.each do |style|
56
- delete realpath(style)
57
- end
58
- end
59
- end
60
-
61
- protected
62
-
63
- def delete(realpath)
64
- if File.exist? realpath
65
- File.delete realpath
66
- end
67
- end
68
-
69
- def realpath(style=:original)
70
- base_path.join(path(style))
71
- end
72
-
73
- def base_path
74
- @base_path ||= begin
75
- if attachment.private?
76
- Rails.root.join 'private'
77
- else
78
- Rails.root.join 'public'
79
- end
80
- end
81
- end
82
-
83
- def base_url
84
- @base_url ||= begin
85
- if Attachs.config.base_url.present?
86
- Pathname.new Attachs.config.base_url
87
- else
88
- Pathname.new '/'
89
- end
90
- end
91
- end
92
-
93
- end
94
- end
95
- end
@@ -1,22 +0,0 @@
1
- module Attachs
2
- module Types
3
- class Base
4
-
5
- def initialize(attachment)
6
- @attachment = attachment
7
- end
8
-
9
- protected
10
-
11
- attr_reader :attachment
12
-
13
- def storage
14
- @storage ||= begin
15
- klass = (attachment.options[:storage] || Attachs.config.default_storage).to_s.classify
16
- Attachs::Storages.const_get(klass).new(attachment)
17
- end
18
- end
19
-
20
- end
21
- end
22
- end