acts_as_assets 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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