file_presenter.rb
3.62 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
# 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