the_storages 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/app/assets/images/content_types/default.jpg +0 -0
  2. data/app/assets/images/content_types/file_extension_3gp.png +0 -0
  3. data/app/assets/images/content_types/file_extension_7z.png +0 -0
  4. data/app/assets/images/content_types/file_extension_ace.png +0 -0
  5. data/app/assets/images/content_types/file_extension_ai.png +0 -0
  6. data/app/assets/images/content_types/file_extension_aif.png +0 -0
  7. data/app/assets/images/content_types/file_extension_aiff.png +0 -0
  8. data/app/assets/images/content_types/file_extension_amr.png +0 -0
  9. data/app/assets/images/content_types/file_extension_asf.png +0 -0
  10. data/app/assets/images/content_types/file_extension_asx.png +0 -0
  11. data/app/assets/images/content_types/file_extension_bat.png +0 -0
  12. data/app/assets/images/content_types/file_extension_bin.png +0 -0
  13. data/app/assets/images/content_types/file_extension_bmp.png +0 -0
  14. data/app/assets/images/content_types/file_extension_bup.png +0 -0
  15. data/app/assets/images/content_types/file_extension_cab.png +0 -0
  16. data/app/assets/images/content_types/file_extension_cbr.png +0 -0
  17. data/app/assets/images/content_types/file_extension_cda.png +0 -0
  18. data/app/assets/images/content_types/file_extension_cdl.png +0 -0
  19. data/app/assets/images/content_types/file_extension_cdr.png +0 -0
  20. data/app/assets/images/content_types/file_extension_chm.png +0 -0
  21. data/app/assets/images/content_types/file_extension_dat.png +0 -0
  22. data/app/assets/images/content_types/file_extension_divx.png +0 -0
  23. data/app/assets/images/content_types/file_extension_dll.png +0 -0
  24. data/app/assets/images/content_types/file_extension_dmg.png +0 -0
  25. data/app/assets/images/content_types/file_extension_doc.png +0 -0
  26. data/app/assets/images/content_types/file_extension_docx.png +0 -0
  27. data/app/assets/images/content_types/file_extension_dss.png +0 -0
  28. data/app/assets/images/content_types/file_extension_dvf.png +0 -0
  29. data/app/assets/images/content_types/file_extension_dwg.png +0 -0
  30. data/app/assets/images/content_types/file_extension_eml.png +0 -0
  31. data/app/assets/images/content_types/file_extension_eps.png +0 -0
  32. data/app/assets/images/content_types/file_extension_exe.png +0 -0
  33. data/app/assets/images/content_types/file_extension_fla.png +0 -0
  34. data/app/assets/images/content_types/file_extension_flv.png +0 -0
  35. data/app/assets/images/content_types/file_extension_gif.png +0 -0
  36. data/app/assets/images/content_types/file_extension_gz.png +0 -0
  37. data/app/assets/images/content_types/file_extension_hqx.png +0 -0
  38. data/app/assets/images/content_types/file_extension_htm.png +0 -0
  39. data/app/assets/images/content_types/file_extension_html.png +0 -0
  40. data/app/assets/images/content_types/file_extension_ifo.png +0 -0
  41. data/app/assets/images/content_types/file_extension_indd.png +0 -0
  42. data/app/assets/images/content_types/file_extension_iso.png +0 -0
  43. data/app/assets/images/content_types/file_extension_jar.png +0 -0
  44. data/app/assets/images/content_types/file_extension_jpeg.png +0 -0
  45. data/app/assets/images/content_types/file_extension_jpg.png +0 -0
  46. data/app/assets/images/content_types/file_extension_lnk.png +0 -0
  47. data/app/assets/images/content_types/file_extension_log.png +0 -0
  48. data/app/assets/images/content_types/file_extension_m4a.png +0 -0
  49. data/app/assets/images/content_types/file_extension_m4b.png +0 -0
  50. data/app/assets/images/content_types/file_extension_m4p.png +0 -0
  51. data/app/assets/images/content_types/file_extension_m4v.png +0 -0
  52. data/app/assets/images/content_types/file_extension_mcd.png +0 -0
  53. data/app/assets/images/content_types/file_extension_mdb.png +0 -0
  54. data/app/assets/images/content_types/file_extension_mid.png +0 -0
  55. data/app/assets/images/content_types/file_extension_mov.png +0 -0
  56. data/app/assets/images/content_types/file_extension_mp2.png +0 -0
  57. data/app/assets/images/content_types/file_extension_mp4.png +0 -0
  58. data/app/assets/images/content_types/file_extension_mpeg.png +0 -0
  59. data/app/assets/images/content_types/file_extension_mpg.png +0 -0
  60. data/app/assets/images/content_types/file_extension_msi.png +0 -0
  61. data/app/assets/images/content_types/file_extension_mswmm.png +0 -0
  62. data/app/assets/images/content_types/file_extension_ogg.png +0 -0
  63. data/app/assets/images/content_types/file_extension_pdf.png +0 -0
  64. data/app/assets/images/content_types/file_extension_php.png +0 -0
  65. data/app/assets/images/content_types/file_extension_png.png +0 -0
  66. data/app/assets/images/content_types/file_extension_pps.png +0 -0
  67. data/app/assets/images/content_types/file_extension_ps.png +0 -0
  68. data/app/assets/images/content_types/file_extension_psd.png +0 -0
  69. data/app/assets/images/content_types/file_extension_pst.png +0 -0
  70. data/app/assets/images/content_types/file_extension_ptb.png +0 -0
  71. data/app/assets/images/content_types/file_extension_pub.png +0 -0
  72. data/app/assets/images/content_types/file_extension_qbb.png +0 -0
  73. data/app/assets/images/content_types/file_extension_qbw.png +0 -0
  74. data/app/assets/images/content_types/file_extension_qxd.png +0 -0
  75. data/app/assets/images/content_types/file_extension_ram.png +0 -0
  76. data/app/assets/images/content_types/file_extension_rar.png +0 -0
  77. data/app/assets/images/content_types/file_extension_rb.png +0 -0
  78. data/app/assets/images/content_types/file_extension_rm.png +0 -0
  79. data/app/assets/images/content_types/file_extension_rmvb.png +0 -0
  80. data/app/assets/images/content_types/file_extension_rtf.png +0 -0
  81. data/app/assets/images/content_types/file_extension_sea.png +0 -0
  82. data/app/assets/images/content_types/file_extension_ses.png +0 -0
  83. data/app/assets/images/content_types/file_extension_sit.png +0 -0
  84. data/app/assets/images/content_types/file_extension_sitx.png +0 -0
  85. data/app/assets/images/content_types/file_extension_ss.png +0 -0
  86. data/app/assets/images/content_types/file_extension_swf.png +0 -0
  87. data/app/assets/images/content_types/file_extension_tgz.png +0 -0
  88. data/app/assets/images/content_types/file_extension_thm.png +0 -0
  89. data/app/assets/images/content_types/file_extension_tif.png +0 -0
  90. data/app/assets/images/content_types/file_extension_tmp.png +0 -0
  91. data/app/assets/images/content_types/file_extension_torrent.png +0 -0
  92. data/app/assets/images/content_types/file_extension_ttf.png +0 -0
  93. data/app/assets/images/content_types/file_extension_txt.png +0 -0
  94. data/app/assets/images/content_types/file_extension_vcd.png +0 -0
  95. data/app/assets/images/content_types/file_extension_vob.png +0 -0
  96. data/app/assets/images/content_types/file_extension_wav.png +0 -0
  97. data/app/assets/images/content_types/file_extension_wma.png +0 -0
  98. data/app/assets/images/content_types/file_extension_wmv.png +0 -0
  99. data/app/assets/images/content_types/file_extension_wps.png +0 -0
  100. data/app/assets/images/content_types/file_extension_xls.png +0 -0
  101. data/app/assets/images/content_types/file_extension_xpi.png +0 -0
  102. data/app/assets/images/content_types/file_extension_zip.png +0 -0
  103. data/app/assets/images/female.png +0 -0
  104. data/app/assets/images/gear.png +0 -0
  105. data/app/assets/images/male.png +0 -0
  106. data/app/assets/images/new.png +0 -0
  107. data/app/assets/images/rotate_left.png +0 -0
  108. data/app/assets/images/rotate_right.png +0 -0
  109. data/app/assets/javascripts/the_storages/image_crop.js.coffee +69 -0
  110. data/app/assets/javascripts/the_storages/water_mark_switcher.js.coffee +17 -0
  111. data/app/assets/stylesheets/the_storages.css.scss +117 -0
  112. data/app/controllers/concerns/attached_files_actions.rb +37 -0
  113. data/app/controllers/concerns/the_storages_image_processor.rb +20 -0
  114. data/app/helpers/attached_files_list_helper.rb +115 -0
  115. data/app/helpers/file_size_helper.rb +9 -0
  116. data/app/models/concerns/act_as_attached_file.rb +69 -0
  117. data/app/models/concerns/act_as_storage.rb +7 -27
  118. data/app/models/concerns/attachment_processing.rb +46 -0
  119. data/app/models/concerns/has_attached_files.rb +14 -0
  120. data/app/models/concerns/image_manipulation.rb +63 -0
  121. data/app/models/concerns/storage_image_processing.rb +90 -0
  122. data/app/models/concerns/watermark_fu.rb +97 -0
  123. data/app/models/delayed_image_processor.rb +6 -0
  124. data/app/views/the_storages/_form.haml +10 -18
  125. data/app/views/the_storages/_list.haml +5 -39
  126. data/config/initializers/paperclip.rb +39 -0
  127. data/config/locales/en.yml +5 -0
  128. data/config/locales/ru.yml +7 -0
  129. data/config/routes.rb +8 -0
  130. data/db/migrate/20130101010101_attached_files.rb +29 -0
  131. data/db/migrate/20130101010102_change_storages.rb +2 -2
  132. data/fonts.txt +1342 -0
  133. data/lib/generators/the_storages/USAGE +1 -20
  134. data/lib/generators/the_storages/templates/the_storages.rb +10 -0
  135. data/lib/generators/the_storages/the_storages_generator.rb +4 -21
  136. data/lib/the_storages.rb +32 -2
  137. data/lib/the_storages/config.rb +32 -0
  138. data/lib/the_storages/version.rb +1 -1
  139. data/the_storages.gemspec +1 -0
  140. data/vendor/assets/images/Jcrop.gif +0 -0
  141. data/vendor/assets/javascripts/jquery.Jcrop.js +1694 -0
  142. data/vendor/assets/stylesheets/jquery.Jcrop.css +165 -0
  143. metadata +154 -15
  144. data/app/helpers/the_storages_helper.rb +0 -25
  145. data/app/models/uploaded_file.rb +0 -113
  146. data/app/views/the_storages/_new.haml +0 -36
  147. data/db/migrate/20130101010101_uploaded_files.rb +0 -25
  148. data/lib/generators/the_storages/views_generator.rb +0 -43
@@ -0,0 +1,37 @@
1
+ module AttachedFilesActions
2
+ def create
3
+ if params[:files]
4
+ attached_files_msg = []
5
+ attached_files_errors_msg = []
6
+
7
+ params[:files].each do |file|
8
+ attached_file = @storage.attached_files.new
9
+ attached_file.attachment = file
10
+
11
+ saved = attached_file.save
12
+
13
+ attached_files_msg.push attached_file.attachment_file_name if saved
14
+ attached_files_errors_msg.push attached_file.errors.first if !saved
15
+ end
16
+
17
+ flash[:notice] = attached_files_msg.join(', ')
18
+ flash[:error] = attached_files_errors_msg.join(', ')
19
+
20
+ redirect_to [request.referer, :files].join('#')
21
+ end
22
+ end
23
+
24
+ def watermark_switch
25
+ attachment = AttachedFile.find(params[:id])
26
+ attachment.toggle!(:watermark)
27
+ attachment.refresh_base_image
28
+ render nothing: true
29
+ end
30
+
31
+ def destroy
32
+ attachment = AttachedFile.find(params[:id])
33
+ attachment.destroy_processed_files
34
+ attachment.destroy
35
+ redirect_to [request.referer, :files].join('#')
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ module TheStoragesImageProcessor
2
+ def rotate_left
3
+ attached_file = AttachedFile.where(id: params[:id]).first
4
+ attached_file.rotate_left
5
+ redirect_to [request.referer, :files].join('#')
6
+ end
7
+
8
+ def rotate_right
9
+ attached_file = AttachedFile.where(id: params[:id]).first
10
+ attached_file.rotate_right
11
+ redirect_to [request.referer, :files].join('#')
12
+ end
13
+
14
+ def crop_image
15
+ x = params
16
+ attached_file = AttachedFile.where(id: x[:image_id]).first
17
+ attached_file.crop_image(:main_preview, x[:x], x[:y], x[:w], x[:h], x[:img_w])
18
+ render text: attached_file.url(:main_preview, nocache: true)
19
+ end
20
+ end
@@ -0,0 +1,115 @@
1
+ # encoding: UTF-8
2
+
3
+ # DOC:
4
+ # We use Helper Methods for tree building,
5
+ # because it's faster than View Templates and Partials
6
+
7
+ # SECURITY note
8
+ # Prepare your data on server side for rendering
9
+ # or use h.html_escape(node.content)
10
+ # for escape potentially dangerous content
11
+ module AttachedFilesListHelper
12
+ module Render
13
+ class << self
14
+ attr_accessor :h, :options
15
+
16
+ def render_node(h, options)
17
+ @h, @options = h, options
18
+ @node = options[:node]
19
+
20
+ "
21
+ <li data-node-id='#{ @node.id }'>
22
+ <div class='item'>
23
+ <i class='handle'></i>
24
+ #{ rotate_links }
25
+ <div class='preview_pic'>#{build_preview_pic}</div>
26
+ <div class='file_block'>
27
+ #{ show_link }
28
+ #{ url_input }
29
+ #{ watermark_switch }
30
+ #{ show_size }
31
+ </div>
32
+ #{ controls }
33
+ </div>
34
+ #{ children }
35
+ </li>
36
+ "
37
+ end
38
+
39
+ def current_host
40
+ h.request.protocol + h.request.host_with_port
41
+ end
42
+
43
+ def url_input
44
+ opts = {nocache: false, timestamp: false}
45
+ url = @node.is_image? ? @node.url(:base, opts) : @node.url(:original, opts)
46
+ "<div class='url_input'>URL: <input class='file_url' value='#{current_host + url}'></div>"
47
+ end
48
+
49
+ def show_size
50
+ "<div class='fsize'>#{@node.mb_size}</div>"
51
+ end
52
+
53
+ def watermark_switch
54
+ if @node.is_image?
55
+ link = if @node.watermark
56
+ "<span class='wm_on'>Вкл.</span>"
57
+ else
58
+ "<span class='wm_off'>Выкл.</span>"
59
+ end
60
+
61
+ "<div class='watermark_switcher'>Водный знак: #{link}</div>"
62
+ end
63
+ end
64
+
65
+ def rotate_links
66
+ if @node.is_image?
67
+ left = h.link_to '', h.rotate_left_url(@node), method: :patch, class: :left
68
+ right = h.link_to '', h.rotate_right_url(@node), method: :patch, class: :right
69
+ "<div class='rotate'>#{left} #{right}</div>"
70
+ end
71
+ end
72
+
73
+ def build_preview_pic
74
+ if @node.is_image?
75
+ src = @node.url(:preview)
76
+ url = @node.url(:base)
77
+ "<a href='#{url}'><img src='#{src}'></a>"
78
+ else
79
+ klass = @node.file_css_class
80
+ url = @node.url
81
+ "<a href='#{url}'><i class='#{klass}'></i></a>"
82
+ end
83
+ end
84
+
85
+ def show_link
86
+ node = options[:node]
87
+ ns = options[:namespace]
88
+ title_field = options[:title]
89
+ title = node.send(title_field)
90
+ url = @node.is_image? ? @node.url(:base) : @node.url
91
+ "<h4>#{ h.link_to(title, url)}</h4>"
92
+ end
93
+
94
+ def controls
95
+ node = options[:node]
96
+
97
+ edit_path = h.url_for(:controller => options[:klass].pluralize, :action => :edit, :id => node)
98
+ show_path = h.url_for(:controller => options[:klass].pluralize, :action => :show, :id => node)
99
+
100
+ "
101
+ <div class='controls'>
102
+ #{ h.link_to '', show_path, :class => :delete, :method => :delete, :data => { :confirm => 'Are you sure?' } }
103
+ </div>
104
+ "
105
+ end
106
+
107
+ def children
108
+ unless options[:children].blank?
109
+ "<ol class='nested_set'>#{ options[:children] }</ol>"
110
+ end
111
+ end
112
+
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,9 @@
1
+ module FileSizeHelper
2
+ def self.mb_size(bytes)
3
+ [sprintf("%.3f", bytes.to_f/1.megabyte.to_f), I18n.t('file_size_helper.mb')].join('&nbsp;')
4
+ end
5
+
6
+ def mb_size(bytes)
7
+ FileSizeHelper.mb_size(bytes)
8
+ end
9
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+ module ActAsAttachedFile
3
+ extend ActiveSupport::Concern
4
+ include AttachmentProcessing
5
+ include StorageImageProcessing
6
+
7
+ included do
8
+ IMAGE_EXTS = %w[jpg jpeg pjpeg png x-png gif bmp]
9
+ IMAGE_CONTENT_TYPES = IMAGE_EXTS.map{ |e| "image/#{e}" }
10
+
11
+ belongs_to :user
12
+ belongs_to :storage, polymorphic: true
13
+ acts_as_nested_set scope: [:user_id, :storage_id, :storage_type]
14
+ include TheSortableTree::Scopes
15
+
16
+ before_validation :generate_file_name, on: :create
17
+ after_create :recalculate_storage_counters!
18
+ after_destroy :recalculate_storage_counters!
19
+ scope :images, ->{ where(attachment_content_type: IMAGE_CONTENT_TYPES) }
20
+ end
21
+
22
+ def file_css_class
23
+ 'f_' + TheStorages.file_ext(attachment_file_name)
24
+ end
25
+
26
+ # HELPERS
27
+ def title
28
+ attachment_file_name
29
+ end
30
+
31
+ def file_name
32
+ TheStorages.file_name(attachment_file_name)
33
+ end
34
+
35
+ def content_type
36
+ attachment_content_type
37
+ end
38
+
39
+ def mb_size
40
+ FileSizeHelper.mb_size(attachment_file_size)
41
+ end
42
+
43
+ def path style = nil
44
+ attachment.path(style)
45
+ end
46
+
47
+ def url style = nil, opts = {}
48
+ url = attachment.url(style, opts)
49
+ return url unless opts[:nocache]
50
+ rnd = (rand*1000000).to_i.to_s
51
+ url =~ /\?/ ? (url + rnd) : (url + '?' + rnd)
52
+ end
53
+
54
+ # BASE HELPERS
55
+ def is_image?
56
+ IMAGE_EXTS.include? TheStorages.file_ext(attachment_file_name)
57
+ end
58
+
59
+ def generate_file_name
60
+ file_name = attachment.instance_read(:file_name)
61
+ file_name = TheStorages.slugged_file_name(file_name)
62
+ attachment.instance_write :file_name, file_name
63
+ end
64
+
65
+ # CALLBACKS
66
+ def recalculate_storage_counters!
67
+ storage.recalculate_storage_counters!
68
+ end
69
+ end
@@ -2,35 +2,15 @@ module ActAsStorage
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- has_many :uploaded_files, as: :storage
6
-
7
- before_update :recalculate_files_data
8
- after_update :recalculate_files_data_for_user
9
- after_destroy :recalculate_files_data_for_user
5
+ has_many :attached_files, as: :storage
10
6
  end
11
7
 
12
- def recalculate_files_data
13
- sum = 0
14
- files = self.uploaded_files.active
15
-
16
- files.each{ |f| sum += f.file_file_size }
17
- self.files_size = sum
18
- self.files_count = files.size
19
- end
20
-
21
- def recalculate_files_data_for_user
22
- user = self.user
23
- storages = user.storages.active | user.recipes.active | user.pages.active | user.articles.active
24
- files_size = 0
25
- files_count = 0
26
-
27
- storages.each do |s|
28
- files_size += s.files_size
29
- files_count += s.files_count
30
- end
8
+ def recalculate_storage_counters!
9
+ af = attached_files.pluck(:attachment_file_size)
10
+ self.storage_files_count = af.count
11
+ self.storage_files_size = af.sum
12
+ save
31
13
 
32
- user.files_size = files_size
33
- user.files_count = files_count
34
- user.save(:validation => false)
14
+ self.try(:user).try(:recalculate_all_attached_files!)
35
15
  end
36
16
  end
@@ -0,0 +1,46 @@
1
+ module AttachmentProcessing
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ attr_accessor :image_processing
6
+ before_create :set_processing_flags
7
+ after_commit :delayed_file_processing
8
+
9
+ has_attached_file :attachment,
10
+ default_url: ":rails_root/public/system/uploads/default/:style-missing.jpg",
11
+ path: ":rails_root/public/system/storages/:storage_type/:storage_id/:style/:filename",
12
+ url: "/system/storages/:storage_type/:storage_id/:style/:filename"
13
+
14
+ validates_attachment_size :attachment,
15
+ in: 10.bytes..5.megabytes,
16
+ message: I18n.translate('the_storages.validation.attachment_file_size')
17
+
18
+ validates :attachment_file_name,
19
+ uniqueness: {
20
+ scope: [:user_id, :storage_type, :storage_id],
21
+ message: I18n.translate('the_storages.validation.uniq_attachment_file_name')
22
+ }
23
+ end
24
+
25
+ def set_processing_flags
26
+ if is_image?
27
+ self.processing = :processing
28
+ self.image_processing = true
29
+ end
30
+ end
31
+
32
+ # DELAYED JOB
33
+ def delayed_file_processing
34
+ if is_image? && image_processing
35
+ self.image_processing = false
36
+ job = DelayedImageProcessor.new(self)
37
+
38
+ job.perform
39
+ # Delayed::Job.enqueue job, queue: :image_processing, run_at: Proc.new { 10.seconds.from_now }
40
+ else
41
+ # if it's not image
42
+ # Upload file and recalculate
43
+ recalculate_storage_counters!
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ module HasAttachedFiles
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ has_many :all_attached_files, class_name: :AttachedFile, foreign_key: :user_id
6
+ end
7
+
8
+ def recalculate_all_attached_files
9
+ af = all_attached_files.pluck(:attachment_file_size)
10
+ self.all_attached_files_count = af.count
11
+ self.all_attached_files_size = af.sum
12
+ save
13
+ end
14
+ end
@@ -0,0 +1,63 @@
1
+ module ImageManipulation
2
+ extend ActiveSupport::Concern
3
+
4
+ # HELPERS
5
+ def landscape? image
6
+ image[:width] > image[:height]
7
+ end
8
+
9
+ def portrait? image
10
+ image[:width] < image[:height]
11
+ end
12
+
13
+ # Fu
14
+ def rotate_image src, dest, angle
15
+ img = MiniMagick::Image.open(src)
16
+ img.rotate(angle)
17
+ img.write(dest)
18
+ end
19
+
20
+ def rotate_attached_image angle
21
+ src = path
22
+ rotate_image(src,src,angle)
23
+ refresh_base_image
24
+ end
25
+
26
+ def rotate_left
27
+ rotate_attached_image "-90"
28
+ end
29
+
30
+ def rotate_right
31
+ rotate_attached_image "90"
32
+ end
33
+
34
+ def resize_to_larger_side image, side_size
35
+ if image[:width] > side_size.to_i
36
+ landscape?(image) ?
37
+ image.resize("#{side_size}x") :
38
+ image.resize("x#{side_size}")
39
+ end
40
+
41
+ image
42
+ end
43
+
44
+ def resize_to_larger_side! src, side_size
45
+ image = MiniMagick::Image.open(src)
46
+ image = resize_to_larger_side(image, side_size)
47
+ image.write src
48
+ end
49
+
50
+ # IMAGE CROP
51
+ def crop_image src, dest, x0 = 0, y0 = 0, w = 100, h = 100, scale = 1
52
+ image = MiniMagick::Image.open src
53
+
54
+ x_shift = (x0.to_f * scale).to_i
55
+ y_shift = (y0.to_f * scale).to_i
56
+
57
+ w = (w.to_f * scale).to_i
58
+ h = (h.to_f * scale).to_i
59
+
60
+ image.crop "#{w}x#{h}+#{x_shift}+#{y_shift}"
61
+ image.write dest
62
+ end
63
+ end
@@ -0,0 +1,90 @@
1
+ # encoding: UTF-8
2
+ module StorageImageProcessing
3
+ include WatermarkFu
4
+ include ImageManipulation
5
+
6
+ def draw_watermark
7
+ return false unless need_watermark?
8
+ build_watermarks
9
+ put_watermark_on_base_image
10
+ end
11
+
12
+ def build_base_images
13
+ resize_src_image
14
+ refresh_base_image
15
+
16
+ # set process state
17
+ src_size = File.size?(path)
18
+ update(processing: :finished, attachment_file_size: src_size)
19
+ end
20
+
21
+ def create_img_dir_path path
22
+ _path = path.split('/')[0...-1].join('/')
23
+ FileUtils.mkdir_p _path
24
+ end
25
+
26
+ # IMAGE PROCESSING
27
+ def prepare_image src, dest, larger_side
28
+ image = MiniMagick::Image.open src
29
+ image.auto_orient
30
+ resize_to_larger_side(image, larger_side)
31
+ image.strip
32
+ create_img_dir_path(dest)
33
+ image.write(dest)
34
+ end
35
+
36
+ def build_square_image src, dest, side = 100
37
+ image = MiniMagick::Image.open src
38
+
39
+ min_size = image[:width]
40
+ shift = { x: 0, y: 0}
41
+
42
+ if landscape?(image)
43
+ min_size = image[:height]
44
+ shift[:x] = (image[:width] - min_size) / 2
45
+ elsif portrait?(image)
46
+ min_size = image[:width]
47
+ shift[:y] = (image[:height] - min_size) / 2
48
+ end
49
+
50
+ x0 = shift[:x]
51
+ y0 = shift[:y]
52
+ w = h = min_size
53
+
54
+ image.crop "#{w}x#{h}+#{x0}+#{y0}"
55
+ image.resize "#{side}x#{side}!"
56
+
57
+ create_img_dir_path(dest)
58
+ image.write dest
59
+ end
60
+
61
+ def build_correct_preview
62
+ src = path
63
+ preview = path :preview
64
+ build_square_image(src, preview, 100)
65
+ end
66
+
67
+ def build_base_image
68
+ src = path
69
+ base = path :base
70
+ prepare_image(src, base, TheStorages.config.base_larger_side)
71
+ end
72
+
73
+ def refresh_base_image
74
+ build_base_image
75
+ build_correct_preview
76
+ draw_watermark
77
+ end
78
+
79
+ def resize_src_image
80
+ src = path
81
+ prepare_image(src, src, TheStorages.config.original_larger_side)
82
+ end
83
+
84
+ def destroy_processed_files
85
+ base = path :base
86
+ preview = path :preview
87
+
88
+ FileUtils.rm([base, preview], force: true)
89
+ end
90
+ end