acts_as_assets 0.1.1 → 0.2.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.
Files changed (32) hide show
  1. data/README.md +3 -0
  2. data/app/controllers/acts_as_assets/assets_controller.rb +48 -31
  3. data/app/helpers/acts_as_assets/assets_helper.rb +47 -4
  4. data/app/views/acts_as_assets/assets/_asset.html.erb +12 -0
  5. data/app/views/acts_as_assets/assets/_asset_multiple_upload.html.erb +6 -0
  6. data/app/views/acts_as_assets/assets/_asset_upload.html.erb +9 -0
  7. data/app/views/acts_as_assets/assets/_assets.html.erb +6 -0
  8. data/app/views/acts_as_assets/assets/_upload_link.html.erb +6 -0
  9. data/app/views/acts_as_assets/assets/create.js.erb +1 -1
  10. data/app/views/acts_as_assets/assets/destroy.js.erb +1 -1
  11. data/app/views/acts_as_assets/assets/index.html.erb +2 -12
  12. data/config/initializers/inflections.rb +14 -0
  13. data/config/locales/it.yml +2 -2
  14. data/lib/acts_as_assets/base.rb +66 -27
  15. data/lib/acts_as_assets/engine.rb +3 -0
  16. data/lib/acts_as_assets/form_helper.rb +42 -0
  17. data/lib/acts_as_assets/paperclip/interpolations.rb +1 -1
  18. data/lib/acts_as_assets/unique_asset.rb +4 -3
  19. data/lib/acts_as_assets/version.rb +1 -1
  20. data/spec/acts_as_assets_spec.rb +54 -52
  21. data/spec/controllers/assets_controller_spec.rb +21 -67
  22. data/spec/dummy/db/test.sqlite3 +0 -0
  23. data/spec/dummy/log/test.log +64789 -20346
  24. data/spec/routing/assets_routing_spec.rb +6 -0
  25. data/spec/spec_helper.rb +43 -17
  26. data/spec/support/book.rb +1 -2
  27. data/spec/support/chapter.rb +17 -0
  28. data/spec/support/chapters_assets_controller.rb +2 -0
  29. data/spec/support/tipi_pannello_assets_controller.rb +4 -0
  30. data/spec/support/tipo_pannello.rb +22 -0
  31. data/spec/unique_asset_spec.rb +4 -12
  32. metadata +85 -19
data/README.md CHANGED
@@ -0,0 +1,3 @@
1
+ = ActsAsAssets
2
+
3
+ This project rocks and uses MIT-LICENSE.
@@ -1,37 +1,46 @@
1
1
  class ActsAsAssets::AssetsController < ApplicationController
2
2
  include ActsAsAssets::AssetsHelper
3
3
  helper_method :destroy_path
4
- before_filter "assign_root_model"
5
- before_filter "assign_target", :only => [:index,:destroy]
4
+
5
+ before_filter :load_type
6
+ before_filter :assign_target, :only => [:index, :destroy]
7
+ before_filter :load_assets, :only => [:index, :destroy]
6
8
 
7
9
  def index
8
- load_assets
10
+ puts "klazz.base_model: #{klazz.base_model}"
11
+ puts "klazz.foreign_key_name: #{klazz.foreign_key_name}"
12
+ puts "params[klazz.foreign_key_name]: #{params[klazz.foreign_key_name]}"
13
+ puts "klazz.base_model.find(CGI.unescape(params[klazz.foreign_key_name])): #{klazz.base_model.find(CGI.unescape(params[klazz.foreign_key_name]))}"
14
+ @model = klazz.base_model.find(CGI.unescape(params[klazz.foreign_key_name]))
9
15
  respond_to do |format|
10
- format.html{render :layout => false}
11
- format.json{render :json => @assets}
16
+ format.html { render :layout => false }
17
+ format.json { render :json => @assets }
12
18
  end
13
19
  end
14
20
 
15
21
  def create
16
- name = root_model_name
17
- klazz = ([name.pluralize.camelize] << camelize_type.flatten).join('::')
18
- @asset = klazz.constantize.create(:asset => params[:file],
19
- :asset_content_type => MIME::Types.type_for(params[:file].original_filename)[0].to_s,
20
- "#{name}".to_sym => instance_variable_get("@#{name}".to_sym))
22
+ @model = klazz.base_model.find(CGI.unescape(params[klazz.foreign_key_name]))
23
+ @asset = klazz.create(
24
+ :asset => params[:file],
25
+ :asset_content_type => mime_type(params[:file]),
26
+ klazz.base_model_sym => @model)
21
27
 
28
+ @asset_partial = partial_to_use(@asset)
22
29
  respond_to do |format|
23
30
  if @asset.valid?
31
+ load_assets
24
32
  format.js
25
33
  else
26
- format.js { render :json =>{:success => false, :errors => @asset.errors}}
34
+ format.js { render :json => {:success => false, :errors => @asset.errors} }
27
35
  end
28
36
  end
29
37
  end
30
38
 
31
39
  def destroy
32
-
33
40
  begin
34
- @asset = instance_variable_get("@#{root_model_name}").send(:assets).find_by_id(params[:asset_id])
41
+ @model = klazz.base_model.find(CGI.unescape(params[klazz.foreign_key_name]))
42
+ @asset = klazz.find_by_id(params[:asset_id])
43
+ @asset_partial = partial_to_use(@asset)
35
44
  @asset.destroy
36
45
  rescue Exception => e
37
46
  error = e.message
@@ -41,7 +50,7 @@ class ActsAsAssets::AssetsController < ApplicationController
41
50
  if error.nil?
42
51
  format.js
43
52
  else
44
- format.js { render :json => {:success => false, :errors => error}}
53
+ format.js { render :json => {:success => false, :errors => error} }
45
54
  end
46
55
  end
47
56
 
@@ -49,42 +58,50 @@ class ActsAsAssets::AssetsController < ApplicationController
49
58
 
50
59
  def get
51
60
  begin
52
- @asset = instance_variable_get("@#{root_model_name}").send(:assets).find(params[:asset_id])
61
+ @asset = klazz.find(params[:asset_id])
62
+
63
+ send_file(file_to_download_path, {:filename => @asset.asset.to_file.original_filename, :content_type => @asset.asset_content_type, :disposition => 'inline'})
64
+
53
65
  rescue ActiveRecord::RecordNotFound
54
- respond_with_404 and return
66
+ respond_with_404
55
67
  end
56
- @path = params[:style].nil? ? @asset.asset.path : @asset.asset.path(params[:style])
57
- send_file(@path, {:filename => @asset.asset.to_file.original_filename, :content_type => @asset.asset_content_type, :disposition => 'inline'})
58
68
  end
59
69
 
60
-
61
70
  private
71
+ def file_to_download_path
72
+ @path = params[:style].nil? ? @asset.asset.path : @asset.asset.path(params[:style])
73
+ end
74
+
75
+ def partial_to_use(asset)
76
+ asset.multiple? ? "acts_as_assets/assets/asset_multiple_upload" : "acts_as_assets/assets/asset_upload"
77
+ end
62
78
 
63
79
  def load_assets
64
- name = root_model_name
65
- klazz = ([name.pluralize.camelize] << camelize_type.flatten).join('::')
66
- @assets = klazz.constantize.send(:where,"#{name}_id".to_sym => params["#{name}_id".to_sym])
80
+ @assets = klazz.where(klazz.foreign_key_name => CGI.unescape(params[klazz.foreign_key_name]))
67
81
  end
68
82
 
69
- def assign_root_model
70
- name = root_model_name
71
- instance_variable_set "@#{name}", name.camelize.constantize.send(:find, params["#{name}_id".to_sym])
83
+ def klazz
84
+ ([self.class.to_s.split('::').first] << camelize_type).join('::').constantize
72
85
  end
73
86
 
74
- def root_model_name
75
- ActiveSupport::Inflector.underscore(self.class.to_s.split('::').first.singularize)
87
+ ## takes a type params string like "my/asset/type_of_documento" and convert into [My,Asset,TypeOfDocument]
88
+ def camelize_type
89
+ params[:type].split('/').map { |i| i.camelize }.flatten
76
90
  end
77
91
 
78
92
  def assign_target
79
93
  @target = params[:target]
80
94
  end
81
95
 
82
- # takes a type params string like "my/asset/type_of_documento" and convert into [My,Asset,TypeOfDocument]
83
- def camelize_type
84
- params[:type].split('/').collect{|i|i.camelize}
96
+ def mime_type(file)
97
+ MIME::Types.type_for(file.original_filename)[0].to_s
98
+ end
99
+
100
+ def load_type
101
+ raise ":type of asset is mandatory and not specified" unless params[:type]
102
+ @type = params[:type]
85
103
  end
86
104
 
87
- private
88
105
 
89
106
  def respond_with_404
90
107
  render :file => "#{Rails.root}/public/404.html", :status => :not_found
@@ -1,9 +1,52 @@
1
1
  module ActsAsAssets::AssetsHelper
2
+ def destroy_path(asset, model, target, type)
3
+ send(destroy_method_for(asset), model, {:asset_id => asset.id, :target => target, :type => type})
4
+ end
5
+
6
+ def destroy_method_for(asset)
7
+ "#{name_from(asset)}_destroy_asset_path".to_sym
8
+ end
9
+
10
+ def name_from(asset)
11
+ asset.class.base_model_name
12
+ end
13
+
14
+ def asset_target
15
+ @type.split('/').join('_')
16
+ end
17
+
18
+ def upload_complete_js_function
19
+ "function(id, fileName, responseJSON, qq){K.allegati.onComplete(id, fileName, responseJSON, qq,'#{asset_target}');}"
20
+ end
21
+ def asset_action(model)
22
+ method_name = "#{model.class.model_name.split('::').first.underscore.singularize}_create_asset_path".to_sym
23
+ self.send(method_name, model, :type => @type, :format => :js)
24
+ end
2
25
 
3
- def destroy_path doc, target
4
- name = ActiveSupport::Inflector.underscore(doc.class.to_s.split('::').first.singularize)
5
- method = "#{name}_destroy_asset_path"
6
- send(method.to_sym, instance_variable_get("@#{name}"), :asset_id => doc.id, :target => target)
26
+ def destroy_file_path(asset, model)
27
+ destroy_path(asset, model, asset_target, @type)
7
28
  end
8
29
 
30
+ def destroy_link(asset, model)
31
+ link_to(I18n.translate('destroy'), destroy_file_path(asset, model), {:method => :delete, :confirm => 'Sei Sicuro?', :remote => true})
32
+ end
33
+
34
+ def asset_label
35
+ defined?(type_label).nil? ? @type.split('/').last.to_s.humanize : type_label
36
+ end
37
+
38
+ def asset_id
39
+ asset_target
40
+ end
41
+
42
+ def asset_file_name(asset)
43
+ asset.asset.to_file.original_filename
44
+ end
45
+ def asset_file_path(asset)
46
+ asset.asset.url
47
+ end
48
+
49
+ def assets_body
50
+ j render(:partial => @asset_partial, :locals => {:assets => Array(@assets), :model => @model})
51
+ end
9
52
  end
@@ -0,0 +1,12 @@
1
+ <% if asset.displayable? %>
2
+ <li>
3
+ <%= link_to("#{asset.asset.url(:original)}&type=#{URI.encode(@type)}", :class => "zoom", :rel => "immagine_sito") {image_tag("#{asset.asset.url(:thumb)}&type=#{URI.encode(@type)}", :alt => 'Apri Immagine')}%>
4
+ <div><%= asset.asset.to_file.original_filename %></div>
5
+ <%= destroy_link(asset, model) %>
6
+ </li>
7
+ <% else %>
8
+ <li>
9
+ <%= link_to(asset.asset.to_file.original_filename, "#{asset.asset.url}&type=#{@type}") %>
10
+ <%= destroy_link(asset, model) %>
11
+ </li>
12
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <%# encoding: utf-8 %>
2
+ <% assets ||= @assets %>
3
+ <div id="<%=asset_id%>" class="multiple assets">
4
+ <%= render :partial => "acts_as_assets/assets/upload_link", :locals => {:multiple => true, :model => model} %>
5
+ <%= render :partial => "acts_as_assets/assets/assets", :locals => {:assets => Array(assets), :model => model} %>
6
+ </div>
@@ -0,0 +1,9 @@
1
+ <%# encoding: utf-8 %>
2
+ <% assets ||= @assets %>
3
+ <div id="<%=asset_id%>" class="multiple assets">
4
+ <% if Array(assets).empty? %>
5
+ <%= render :partial => "acts_as_assets/assets/upload_link", :locals => {:multiple => false, :model => model} %>
6
+ <% else %>
7
+ <%= render :partial => "acts_as_assets/assets/assets", :locals => {:assets => Array(assets), :model => model} %>
8
+ <% end %>
9
+ </div>
@@ -0,0 +1,6 @@
1
+ <ul>
2
+ <%= render :partial => 'acts_as_assets/assets/asset', :collection => assets, :locals => {:model => model} %>
3
+ </ul>
4
+ <script type="text/javascript">
5
+ $(function () { $("a.zoom").fancybox(); });
6
+ </script>
@@ -0,0 +1,6 @@
1
+ <%= uploader_field_tag asset_target,
2
+ :action => asset_action(model),
3
+ :uploadButtonText => t('aggiungi'),
4
+ :multiple => multiple,
5
+ :params => {:authenticity_token => form_authenticity_token, :target => asset_target},
6
+ :onComplete => upload_complete_js_function %>
@@ -1 +1 @@
1
- {"success":"true"}
1
+ {"asset_id": "<%= asset_id %>","body": "<%= assets_body %>","success": true}
@@ -1 +1 @@
1
- {"success":"true"}
1
+ $("#<%= asset_id %>").html("<%= assets_body %>");
@@ -1,12 +1,2 @@
1
- <%# coding: utf-8 %>
2
- <% @assets.each do |doc| %>
3
-
4
- <div class="grid_6 document_link">
5
- <%= link_to doc.asset.to_file.original_filename, doc.asset.url %>
6
- <%= link_to t('destroy'), destroy_path(doc,@target),
7
- :method => :delete, :confirm => 'Sei Sicuro?', :remote => true %>
8
- </div>
9
-
10
- <div class="clear"></div>
11
-
12
- <% end %>
1
+ <%# encoding: utf-8 %>
2
+ <% render :partial => 'acts_as_assets/assets/asset_multiple_upload', :locals => {:model => @model, :multiple => true} %>
@@ -0,0 +1,14 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new inflection rules using the following format
4
+ # (all these examples are active by default):
5
+ # ActiveSupport::Inflector.inflections do |inflect|
6
+ # inflect.plural /^(ox)$/i, '\1en'
7
+ # inflect.singular /^(ox)en/i, '\1'
8
+ # inflect.irregular 'person', 'people'
9
+ # inflect.uncountable %w( fish sheep )
10
+ # end
11
+
12
+ ActiveSupport::Inflector.inflections do |inflect|
13
+ inflect.irregular 'tipo_pannello', 'tipi_pannello'
14
+ end
@@ -1,3 +1,3 @@
1
1
  it:
2
- acts_as_assets:
3
- unique_asset_error: 'Un solo documento di questo tipo può essere caricato. Eliminare il file attuale per sostituirlo.'
2
+ acts_as_assets:
3
+ unique_asset_error: 'Un solo documento di questo tipo può essere caricato. Eliminare il file attuale per sostituirlo.'
@@ -1,73 +1,112 @@
1
1
  require "acts_as_assets/paperclip/interpolations"
2
2
  require "acts_as_assets/unique_asset"
3
+ require "h5_uploader"
3
4
 
4
5
  module ActsAsAssets
5
6
 
6
7
  module Base
8
+ extend ActiveSupport::Concern
7
9
 
8
- def self.included base
9
- base.class_eval do
10
- extend ClassMethods
11
- end
10
+ included do
11
+ extend ClassMethods
12
12
  end
13
-
14
13
  end
15
14
 
16
15
  module ClassMethods
17
16
 
18
17
  def acts_as_assets *args
18
+ cattr_accessor :foreign_key_name
19
+ cattr_accessor :base_model_name
20
+ cattr_accessor :base_model
21
+
19
22
  include InstanceMethods
20
- belongs_to root_model
21
23
 
22
24
  options = args.extract_options!
25
+
23
26
  paperclip_config = {
24
- :url => options.include?(:styles) ?
25
- "/#{root_model.to_s.pluralize}/:acts_as_assets_root_id/assets/get/:acts_as_assets_asset_id/:style/:acts_as_assets_file_name.:extension" :
26
- "/#{root_model.to_s.pluralize}/:acts_as_assets_root_id/assets/get/:acts_as_assets_asset_id/:acts_as_assets_file_name.:extension",
27
- :path => options.include?(:styles) ? ":acts_as_assets_file_path/:style/:acts_as_assets_file_name.:extension" : ":acts_as_assets_file_path/:acts_as_assets_file_name.:extension"
27
+ :url => options.include?(:styles) ? url_with_styles : url_without_styles,
28
+ :path => options.include?(:styles) ? path_with_styles : path_without_styles
28
29
  }
30
+ self.base_model_name = self.to_s.split('::').first.underscore.singularize
31
+ self.base_model = self.base_model_name.camelize.constantize
32
+ self.foreign_key_name = (options[:foreign_key] || "#{self.base_model_name}_id").to_sym
33
+
34
+ belongs_to base_model_sym, :foreign_key => self.foreign_key_name
29
35
  has_attached_file :asset, paperclip_config.merge(options)
30
- before_create :touch_counter
36
+
37
+ before_create :increment_counter
38
+
39
+ end
40
+
41
+ def url_with_styles
42
+ "/#{_base_model_name.pluralize}/:acts_as_assets_root_id/assets/get/:acts_as_assets_asset_id/:style/:acts_as_assets_file_name.:extension"
43
+ end
44
+
45
+ def url_without_styles
46
+ "/#{_base_model_name.pluralize}/:acts_as_assets_root_id/assets/get/:acts_as_assets_asset_id/:acts_as_assets_file_name.:extension"
47
+ end
48
+
49
+ def path_with_styles
50
+ ":acts_as_assets_file_path/:style/:acts_as_assets_file_name.:extension"
51
+ end
52
+
53
+ def path_without_styles
54
+ ":acts_as_assets_file_path/:acts_as_assets_file_name.:extension"
55
+ end
56
+
57
+ def _base_model_name
58
+ self.to_s.split('::').first.underscore.singularize
31
59
  end
32
60
 
33
- def root_model
34
- ActiveSupport::Inflector.underscore(self.to_s.split('::').first.singularize).to_sym
61
+ def base_model_sym
62
+ _base_model_name.to_sym
35
63
  end
36
64
 
37
65
  end
38
66
 
39
67
  module InstanceMethods
40
-
41
68
  def acting_as_assets?
42
69
  true
43
70
  end
44
71
 
72
+ def multiple?
73
+ true
74
+ end
75
+
45
76
  private
77
+ def increment_counter
78
+ self.counter = number_of_file_for_type + 1
79
+ end
46
80
 
47
- def touch_counter
48
- max = self.class.maximum(:counter, :conditions => {"#{self.class.root_model}_id".to_sym => self.send("#{self.class.root_model}_id".to_sym)})
49
- self.counter = max.nil? ? 1 : max+1
81
+ def number_of_file_for_type
82
+ self.class.maximum(:counter, :conditions => {self.foreign_key_name => self.send(self.foreign_key_name)}).to_i
50
83
  end
51
84
 
52
- def root_id
53
- send(self.class.root_model).id
85
+ def foreign_key_value
86
+ self.send(foreign_key_name)
54
87
  end
55
88
 
56
89
  def acts_as_assets_file_path
57
- a = ActiveSupport::Inflector.underscore(self.type).split('/').prepend "public", "system"
58
- a.pop
59
- root_model_index = a.index(self.class.root_model.to_s.pluralize)
60
- a.insert root_model_index + 1,root_id
61
- a.join '/'
90
+ absolute_directory_for_asset_as_array.insert(3, foreign_key_value).join('/')
62
91
  end
63
92
 
64
93
  def acts_as_assets_file_name
65
- a = ActiveSupport::Inflector.underscore(self.type).split('/')
66
- self.counter > 1 ? "#{a.last}_#{counter}" : a.last
94
+ self.counter > 1 ? "#{_file_name}_#{counter}" : _file_name
95
+ end
96
+
97
+ def _file_name
98
+ relative_directory_for_asset_as_array.last
67
99
  end
68
100
 
101
+ def relative_directory_for_asset_as_array
102
+ self.type.underscore.split('/')
103
+ end
104
+
105
+ def absolute_directory_for_asset_as_array
106
+ relative_directory_for_asset_as_array.unshift("public", "system").instance_eval { pop; self }
107
+ end
69
108
  end
70
109
 
71
110
  end
72
111
 
73
- ActiveRecord::Base.send :include, ActsAsAssets::Base
112
+ ActiveRecord::Base.send :include, ActsAsAssets::Base
@@ -1,4 +1,7 @@
1
1
  module ActsAsAssets
2
2
  class Engine < ::Rails::Engine
3
+ initializer "acts_as_assets.add_form_builder_extensions", :after=>"bootstrap_hook" do |app|
4
+ require "acts_as_assets/form_helper"
5
+ end
3
6
  end
4
7
  end
@@ -0,0 +1,42 @@
1
+ module ActionView
2
+ module Helpers
3
+ class FormBuilder
4
+ def asset_upload(method, type)
5
+ @template.asset_upload_tag(@object, method, type)
6
+ end
7
+ def asset_multiple_upload(method, type)
8
+ @template.asset_multiple_upload_tag(@object, method, type)
9
+ end
10
+ def asset_label(method, type)
11
+ @template.asset_label_tag(@object, method, type)
12
+ end
13
+ end
14
+
15
+ module FormTagHelper
16
+ def asset_multiple_upload_tag(model, methods, type)
17
+ asset_upload_helper(model, methods, type, "acts_as_assets/assets/asset_multiple_upload")
18
+ end
19
+
20
+ def asset_upload_tag(model, methods, type)
21
+ asset_upload_helper(model, methods, type, "acts_as_assets/assets/asset_upload")
22
+ end
23
+
24
+ private
25
+
26
+ # +methods+ can be a sym that will be the method name and it will be called
27
+ # against the model passed or can an array of symbols and will be chained in a method call
28
+ # for instance
29
+ # asset_upload_tag(@pratica, [:back_office, :allegati], ...)
30
+ # will call @pratica.back_office.allegati
31
+ def asset_upload_helper(model, methods, type, partial)
32
+ render :partial => partial,
33
+ :locals => {:@type => type, :model => model, :assets => model_assets(methods, model)}
34
+ end
35
+
36
+ def model_assets(methods, model)
37
+ Array(methods).inject(model) {|object, method| object.send(method) }
38
+ end
39
+
40
+ end
41
+ end
42
+ end