file_presenter.rb
3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# All file presenters must extends `FilePresenter` not only to ensure the
# same interface, but also to make `FilePresenter.for(file)` to work.
class FilePresenter
# Will return a encapsulated `UploadedFile` or the same object if no
# one accepts it. That behave allow to give any model to this class,
# like a Article and have no trouble with that.
def self.for(f)
#FIXME This check after the || is redundant but increases the blog_page
# speed considerably.
return f if f.is_a?(FilePresenter ) || (!f.kind_of?(UploadedFile) && !f.kind_of?(Image))
klass = FilePresenter.subclasses.sort_by {|class_instance|
class_instance.accepts?(f) || 0
}.last
klass.accepts?(f) ? klass.new(f) : f
end
def self.base_class
Article
end
def initialize(f)
@file = f
end
# Allows to use the original `UploadedFile` reference.
def encapsulated_file
@file
end
def id
@file.id
end
def reload
@file.reload
self
end
def kind_of?(klass)
@file.kind_of?(klass)
end
# This method must be overridden in subclasses.
#
# If the class accepts the file, return a number that represents the
# priority the class should be given to handle that file. Higher numbers
# mean higher priority.
#
# If the class does not accept the file, return false.
def self.accepts?(f)
nil
end
def download? view = nil
view.blank?
end
def short_description
file_type = if content_type.present?
content_type.sub(/^application\//, '').sub(/^x-/, '').sub(/^image\//, '')
else
_('Unknown')
end
_("File (%s)") % file_type
end
# Define the css classes to style the page fragment with the file related
# content. If you want other classes to identify this area to your
# customized presenter, so do this:
# def css_class_list
# [super, 'myclass'].flatten
# end
def css_class_list
[ @file.css_class_list,
'file-' + self.class.to_s.split(/:+/).map(&:underscore)[1..-1].join('-'),
'content-type_' + self.content_type.split('/')[0],
'content-type_' + self.content_type.gsub(/[^a-z0-9]/i,'-')
].flatten
end
# Enable file presenter to customize the css classes on view_page.rhtml
# You may not overwrite this method on your customized presenter.
def css_class_name
[css_class_list].flatten.compact.join(' ')
end
# The generic icon class-name or the specific file path.
# You may replace this method on your custom FilePresenter.
# See the current used icons class-names in public/designs/icons/tango/style.css
def icon_name
if mime_type
[ mime_type.split('/')[0], mime_type.gsub(/[^a-z0-9]/i, '-') ]
else
'upload-file'
end
end
# Automatic render `file_presenter/<custom>.html.erb` to display your
# custom presenter html content.
# You may not overwrite this method on your customized presenter.
# A variable with the same presenter name will be created to refer
# to the file object.
# Example:
# The `FilePresenter::Image` render `file_presenter/image.html.erb`
# inside the `file_presenter/image.html.erb` you can access the
# required `FilePresenter::Image` instance in the `image` variable.
def to_html(options = {})
file = self
proc do
render :partial => file.class.to_s.underscore,
:locals => { :options => options },
:object => file
end
end
# That makes the presenter to works like any other `UploadedFile` instance.
def method_missing(m, *args)
@file.send(m, *args)
end
end
# Preload FilePresenters to allow `FilePresenter.for()` to work
Dir.glob(File.join('app', 'presenters', '*.rb')) do |file|
load file
end
# Preload FilePresenters from plugins to allow `FilePresenter.for()` to work
Dir.glob(File.join('plugins', '*', 'lib', 'presenters', '*.rb')) do |file|
load file
end