presenting 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -20
- data/README +10 -10
- data/Rakefile +22 -22
- data/app/assets/javascripts/search.js +13 -13
- data/app/assets/stylesheets/details-color.css +7 -7
- data/app/assets/stylesheets/details.css +10 -10
- data/app/assets/stylesheets/form.css +1 -1
- data/app/assets/stylesheets/grid-color.css +71 -71
- data/app/assets/stylesheets/grid.css +64 -64
- data/app/assets/stylesheets/search-color.css +16 -16
- data/app/assets/stylesheets/search.css +45 -45
- data/app/controllers/presentation/assets_controller.rb +42 -42
- data/app/views/presentations/_details.erb +11 -11
- data/app/views/presentations/_field_search.erb +14 -14
- data/app/views/presentations/_form.erb +20 -20
- data/app/views/presentations/_grid.erb +70 -70
- data/app/views/presentations/_search.erb +7 -7
- data/lib/presentation/base.rb +31 -31
- data/lib/presentation/details.rb +21 -21
- data/lib/presentation/field_search.rb +67 -67
- data/lib/presentation/form.rb +149 -149
- data/lib/presentation/grid.rb +162 -160
- data/lib/presentation/search.rb +9 -9
- data/lib/presenting/attribute.rb +51 -51
- data/lib/presenting/configurable.rb +10 -10
- data/lib/presenting/defaults.rb +10 -10
- data/lib/presenting/field_set.rb +26 -26
- data/lib/presenting/form_helpers.rb +51 -51
- data/lib/presenting/helpers.rb +114 -114
- data/lib/presenting/sanitize.rb +19 -19
- data/lib/presenting/search.rb +185 -185
- data/lib/presenting/sorting.rb +87 -87
- data/test/attribute_test.rb +61 -61
- data/test/configurable_test.rb +20 -20
- data/test/details_test.rb +68 -68
- data/test/field_search_test.rb +102 -102
- data/test/field_set_test.rb +46 -46
- data/test/grid_test.rb +246 -239
- data/test/helpers_test.rb +72 -72
- data/test/presenting_test.rb +15 -15
- data/test/r3/Gemfile +7 -7
- data/test/r3/Gemfile.lock +86 -82
- data/test/r3/config/application.rb +12 -12
- data/test/r3/config/boot.rb +6 -6
- data/test/r3/config/database.yml +22 -22
- data/test/r3/config/environment.rb +5 -5
- data/test/r3/config/environments/test.rb +35 -35
- data/test/r3/db/test.sqlite3 +0 -0
- data/test/r3/log/test.log +336 -0
- data/test/r3/public/javascripts/presenting/grid.js +0 -0
- data/test/r3/public/javascripts/presenting/search.js +13 -13
- data/test/r3/public/stylesheets/presenting/details-color.css +7 -7
- data/test/r3/public/stylesheets/presenting/details.css +10 -10
- data/test/r3/public/stylesheets/presenting/form.css +1 -1
- data/test/r3/public/stylesheets/presenting/grid-color.css +71 -71
- data/test/r3/public/stylesheets/presenting/grid.css +64 -64
- data/test/r3/public/stylesheets/presenting/search-color.css +16 -16
- data/test/r3/public/stylesheets/presenting/search.css +45 -45
- data/test/sanitize_test.rb +15 -15
- data/test/search_conditions_test.rb +137 -137
- data/test/search_test.rb +30 -30
- data/test/sorting_test.rb +63 -63
- metadata +74 -74
data/lib/presenting/attribute.rb
CHANGED
@@ -1,51 +1,51 @@
|
|
1
|
-
module Presenting
|
2
|
-
# represents an attribute meant to be read from a record
|
3
|
-
# used for things like Grid and Details.
|
4
|
-
# not intended for things like Form or FieldSearch
|
5
|
-
class Attribute
|
6
|
-
include Presenting::Configurable
|
7
|
-
|
8
|
-
def name=(val)
|
9
|
-
self.value ||= val # don't lazy define :value, because we're about to typecast here
|
10
|
-
if val.is_a? Symbol
|
11
|
-
@name = val.to_s.titleize
|
12
|
-
else
|
13
|
-
@name = val.to_s
|
14
|
-
end
|
15
|
-
end
|
16
|
-
attr_reader :name
|
17
|
-
|
18
|
-
# The short programmatic name for this field. Can be used as a CSS class, sorting name, etc.
|
19
|
-
def id=(val)
|
20
|
-
@id = val.to_s
|
21
|
-
end
|
22
|
-
|
23
|
-
def id
|
24
|
-
@id ||= name.to_s.underscore.gsub(/[^a-z0-9]/i, '_').gsub(/__+/, '_').sub(/_$/, '')
|
25
|
-
end
|
26
|
-
|
27
|
-
# Where a field's value comes from. Depends heavily on the data type you provide.
|
28
|
-
# - String: fixed value (as provided)
|
29
|
-
# - Symbol: a method on the record (no arguments)
|
30
|
-
# - Proc: a custom block that accepts the record as an argument
|
31
|
-
attr_accessor :value
|
32
|
-
|
33
|
-
def value_from(obj) #:nodoc:
|
34
|
-
case value
|
35
|
-
when Symbol: obj.is_a?(Hash) ? obj[value] : obj.send(value)
|
36
|
-
when String: value
|
37
|
-
when Proc: value.call(obj)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# whether html should be sanitize. right now this actually means html escaping.
|
42
|
-
# consider: by default, do not sanitize if value is a String?
|
43
|
-
attr_writer :sanitize
|
44
|
-
def sanitize?
|
45
|
-
unless defined? @sanitize
|
46
|
-
@sanitize = Presenting::Defaults.sanitize_fields
|
47
|
-
end
|
48
|
-
@sanitize
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
1
|
+
module Presenting
|
2
|
+
# represents an attribute meant to be read from a record
|
3
|
+
# used for things like Grid and Details.
|
4
|
+
# not intended for things like Form or FieldSearch
|
5
|
+
class Attribute
|
6
|
+
include Presenting::Configurable
|
7
|
+
|
8
|
+
def name=(val)
|
9
|
+
self.value ||= val # don't lazy define :value, because we're about to typecast here
|
10
|
+
if val.is_a? Symbol
|
11
|
+
@name = val.to_s.titleize
|
12
|
+
else
|
13
|
+
@name = val.to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
attr_reader :name
|
17
|
+
|
18
|
+
# The short programmatic name for this field. Can be used as a CSS class, sorting name, etc.
|
19
|
+
def id=(val)
|
20
|
+
@id = val.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def id
|
24
|
+
@id ||= name.to_s.underscore.gsub(/[^a-z0-9]/i, '_').gsub(/__+/, '_').sub(/_$/, '')
|
25
|
+
end
|
26
|
+
|
27
|
+
# Where a field's value comes from. Depends heavily on the data type you provide.
|
28
|
+
# - String: fixed value (as provided)
|
29
|
+
# - Symbol: a method on the record (no arguments)
|
30
|
+
# - Proc: a custom block that accepts the record as an argument
|
31
|
+
attr_accessor :value
|
32
|
+
|
33
|
+
def value_from(obj) #:nodoc:
|
34
|
+
case value
|
35
|
+
when Symbol: obj.is_a?(Hash) ? obj[value] : obj.send(value)
|
36
|
+
when String: value
|
37
|
+
when Proc: value.call(obj)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# whether html should be sanitize. right now this actually means html escaping.
|
42
|
+
# consider: by default, do not sanitize if value is a String?
|
43
|
+
attr_writer :sanitize
|
44
|
+
def sanitize?
|
45
|
+
unless defined? @sanitize
|
46
|
+
@sanitize = Presenting::Defaults.sanitize_fields
|
47
|
+
end
|
48
|
+
@sanitize
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
module Presenting
|
2
|
-
module Configurable
|
3
|
-
def initialize(options = {}, &block)
|
4
|
-
options.each do |k, v|
|
5
|
-
self.send("#{k}=", v)
|
6
|
-
end
|
7
|
-
yield self if block_given?
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
1
|
+
module Presenting
|
2
|
+
module Configurable
|
3
|
+
def initialize(options = {}, &block)
|
4
|
+
options.each do |k, v|
|
5
|
+
self.send("#{k}=", v)
|
6
|
+
end
|
7
|
+
yield self if block_given?
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/presenting/defaults.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
module Presenting::Defaults
|
2
|
-
# Whether the columns in the Grid should be sortable by default
|
3
|
-
mattr_accessor :grid_is_sortable
|
4
|
-
self.grid_is_sortable = true
|
5
|
-
|
6
|
-
# Whether fields should be sanitized by default
|
7
|
-
mattr_accessor :sanitize_fields
|
8
|
-
self.sanitize_fields = true
|
9
|
-
end
|
10
|
-
|
1
|
+
module Presenting::Defaults
|
2
|
+
# Whether the columns in the Grid should be sortable by default
|
3
|
+
mattr_accessor :grid_is_sortable
|
4
|
+
self.grid_is_sortable = true
|
5
|
+
|
6
|
+
# Whether fields should be sanitized by default
|
7
|
+
mattr_accessor :sanitize_fields
|
8
|
+
self.sanitize_fields = true
|
9
|
+
end
|
10
|
+
|
data/lib/presenting/field_set.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
class Presenting::FieldSet < Array
|
2
|
-
def initialize(field_class, primary, secondary)
|
3
|
-
@klass = field_class
|
4
|
-
@primary_attribute = primary
|
5
|
-
@secondary_attribute = secondary
|
6
|
-
end
|
7
|
-
|
8
|
-
def <<(field)
|
9
|
-
if field.is_a? Hash
|
10
|
-
k, v = *field.to_a.first
|
11
|
-
opts = v.is_a?(Hash) ? v : {@secondary_attribute => v}
|
12
|
-
opts[@primary_attribute] = k
|
13
|
-
else
|
14
|
-
opts = {@primary_attribute => field}
|
15
|
-
end
|
16
|
-
super @klass.new(opts)
|
17
|
-
end
|
18
|
-
|
19
|
-
def [](key)
|
20
|
-
detect{|i| i.send(@primary_attribute) == key}
|
21
|
-
end
|
22
|
-
|
23
|
-
def []=(key, val)
|
24
|
-
self << {key => val}
|
25
|
-
end
|
26
|
-
end
|
1
|
+
class Presenting::FieldSet < Array
|
2
|
+
def initialize(field_class, primary, secondary)
|
3
|
+
@klass = field_class
|
4
|
+
@primary_attribute = primary
|
5
|
+
@secondary_attribute = secondary
|
6
|
+
end
|
7
|
+
|
8
|
+
def <<(field)
|
9
|
+
if field.is_a? Hash
|
10
|
+
k, v = *field.to_a.first
|
11
|
+
opts = v.is_a?(Hash) ? v : {@secondary_attribute => v}
|
12
|
+
opts[@primary_attribute] = k
|
13
|
+
else
|
14
|
+
opts = {@primary_attribute => field}
|
15
|
+
end
|
16
|
+
super @klass.new(opts)
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
detect{|i| i.send(@primary_attribute) == key}
|
21
|
+
end
|
22
|
+
|
23
|
+
def []=(key, val)
|
24
|
+
self << {key => val}
|
25
|
+
end
|
26
|
+
end
|
@@ -1,51 +1,51 @@
|
|
1
|
-
module Presenting::FormHelpers
|
2
|
-
def present(field)
|
3
|
-
send("present_#{field.type}_input", field)
|
4
|
-
end
|
5
|
-
|
6
|
-
def present_readonly_input(field)
|
7
|
-
text_field field.name, :disabled => true, :value => field.value_from(object)
|
8
|
-
end
|
9
|
-
|
10
|
-
def present_string_input(field)
|
11
|
-
text_field field.name, :value => field.value_from(object)
|
12
|
-
end
|
13
|
-
|
14
|
-
def present_hidden_input(field)
|
15
|
-
hidden_field field.name, :value => field.value_from(object)
|
16
|
-
end
|
17
|
-
|
18
|
-
def present_text_input(field)
|
19
|
-
text_area field.name, :value => field.value_from(object)
|
20
|
-
end
|
21
|
-
|
22
|
-
def present_password_input(field)
|
23
|
-
password_field field.name
|
24
|
-
end
|
25
|
-
|
26
|
-
def present_boolean_input(field)
|
27
|
-
check_box field.name
|
28
|
-
end
|
29
|
-
|
30
|
-
def present_dropdown_input(field)
|
31
|
-
view.select_tag "#{object_name}[#{field.name}]", view.options_for_select(field.type_options, object.send(field.name))
|
32
|
-
end
|
33
|
-
alias_method :present_select_input, :present_dropdown_input
|
34
|
-
|
35
|
-
def present_multi_select_input(field)
|
36
|
-
view.select_tag "#{object_name}[#{field.name}][]", view.options_for_select(field.type_options, object.send(field.name)), :multiple => true
|
37
|
-
end
|
38
|
-
|
39
|
-
def present_radios_input(field)
|
40
|
-
field.type_options.collect do |(display, value)|
|
41
|
-
label("#{field.name}_#{value}", display) +
|
42
|
-
radio_button(field.name, value)
|
43
|
-
end.join.html_safe
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def view
|
49
|
-
@template
|
50
|
-
end
|
51
|
-
end
|
1
|
+
module Presenting::FormHelpers
|
2
|
+
def present(field)
|
3
|
+
send("present_#{field.type}_input", field)
|
4
|
+
end
|
5
|
+
|
6
|
+
def present_readonly_input(field)
|
7
|
+
text_field field.name, :disabled => true, :value => field.value_from(object)
|
8
|
+
end
|
9
|
+
|
10
|
+
def present_string_input(field)
|
11
|
+
text_field field.name, :value => field.value_from(object)
|
12
|
+
end
|
13
|
+
|
14
|
+
def present_hidden_input(field)
|
15
|
+
hidden_field field.name, :value => field.value_from(object)
|
16
|
+
end
|
17
|
+
|
18
|
+
def present_text_input(field)
|
19
|
+
text_area field.name, :value => field.value_from(object)
|
20
|
+
end
|
21
|
+
|
22
|
+
def present_password_input(field)
|
23
|
+
password_field field.name
|
24
|
+
end
|
25
|
+
|
26
|
+
def present_boolean_input(field)
|
27
|
+
check_box field.name
|
28
|
+
end
|
29
|
+
|
30
|
+
def present_dropdown_input(field)
|
31
|
+
view.select_tag "#{object_name}[#{field.name}]", view.options_for_select(field.type_options, object.send(field.name))
|
32
|
+
end
|
33
|
+
alias_method :present_select_input, :present_dropdown_input
|
34
|
+
|
35
|
+
def present_multi_select_input(field)
|
36
|
+
view.select_tag "#{object_name}[#{field.name}][]", view.options_for_select(field.type_options, object.send(field.name)), :multiple => true
|
37
|
+
end
|
38
|
+
|
39
|
+
def present_radios_input(field)
|
40
|
+
field.type_options.collect do |(display, value)|
|
41
|
+
label("#{field.name}_#{value}", display) +
|
42
|
+
radio_button(field.name, value)
|
43
|
+
end.join.html_safe
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def view
|
49
|
+
@template
|
50
|
+
end
|
51
|
+
end
|
data/lib/presenting/helpers.rb
CHANGED
@@ -1,114 +1,114 @@
|
|
1
|
-
module Presenting
|
2
|
-
module Helpers
|
3
|
-
def presentation_stylesheets(*args)
|
4
|
-
warn "[DEPRECATION] presentation_stylesheets is deprecated. Please use the stylesheets" <<
|
5
|
-
"that are copied to public/stylesheets/presenting/* on boot."
|
6
|
-
stylesheet_link_tag presentation_stylesheet_path(args.sort.join(','), :format => 'css')
|
7
|
-
end
|
8
|
-
|
9
|
-
def presentation_javascript(*args)
|
10
|
-
warn "[DEPRECATION] presentation_javascript is deprecated. Please use the javascripts" <<
|
11
|
-
"that are copied to public/javascripts/presenting/* on boot."
|
12
|
-
javascript_include_tag presentation_javascript_path(args.sort.join(','), :format => 'js')
|
13
|
-
end
|
14
|
-
|
15
|
-
def present(*args, &block)
|
16
|
-
options = args.length > 1 ? args.extract_options! : {}
|
17
|
-
|
18
|
-
if args.first.is_a? Symbol
|
19
|
-
object, presentation = nil, args.first
|
20
|
-
else
|
21
|
-
object, presentation = args.first, args.second
|
22
|
-
end
|
23
|
-
|
24
|
-
if presentation
|
25
|
-
klass = "Presentation::#{presentation.to_s.camelcase}".constantize rescue nil
|
26
|
-
if klass
|
27
|
-
instance = klass.new(options, &block)
|
28
|
-
instance.presentable = object
|
29
|
-
instance.controller = controller
|
30
|
-
instance.render
|
31
|
-
elsif respond_to?(method_name = "present_#{presentation}")
|
32
|
-
send(method_name, object, options)
|
33
|
-
else
|
34
|
-
raise ArgumentError, "unknown presentation `#{presentation}'"
|
35
|
-
end
|
36
|
-
elsif object.respond_to?(:loaded?) # AssociationProxy
|
37
|
-
present_association(object, options)
|
38
|
-
else
|
39
|
-
present_by_class(object, options)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# presents a text search widget for the given field (a Presentation::FieldSearch::Field, probably)
|
44
|
-
def present_text_search(field, options = {})
|
45
|
-
current_value = (params[:search][field.param][:value] rescue nil)
|
46
|
-
text_field_tag options[:name], h(current_value)
|
47
|
-
end
|
48
|
-
|
49
|
-
# presents a checkbox search widget for the given field (a Presentation::FieldSearch::Field, probably)
|
50
|
-
def present_checkbox_search(field, options = {})
|
51
|
-
current_value = (params[:search][field.param][:value] rescue nil)
|
52
|
-
check_box_tag options[:name], '1', current_value.to_s == '1'
|
53
|
-
end
|
54
|
-
|
55
|
-
# presents a dropdown/select search widget for the given field (a Presentation::FieldSearch::Field, probably)
|
56
|
-
def present_dropdown_search(field, options = {})
|
57
|
-
current_value = (params[:search][field.param][:value] rescue nil)
|
58
|
-
select_tag options[:name], options_for_select(normalize_dropdown_options_to_strings(field.options), current_value)
|
59
|
-
end
|
60
|
-
|
61
|
-
protected
|
62
|
-
|
63
|
-
# We want to normalize the value elements of the dropdown options to strings so that
|
64
|
-
# they will match against params[:search].
|
65
|
-
#
|
66
|
-
# Need to handle the three different dropdown options formats:
|
67
|
-
# * array of strings
|
68
|
-
# * array of arrays
|
69
|
-
# * hash
|
70
|
-
def normalize_dropdown_options_to_strings(options)
|
71
|
-
options.to_a.map do |element|
|
72
|
-
if element.is_a? String
|
73
|
-
[element, element]
|
74
|
-
else
|
75
|
-
[element.first, element.last.to_s]
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# TODO: special handling for associations (displaying activerecords)
|
81
|
-
def present_association(object, options = {})
|
82
|
-
present_by_class(object, options)
|
83
|
-
end
|
84
|
-
|
85
|
-
def present_by_class(object, options = {})
|
86
|
-
case object
|
87
|
-
when Array
|
88
|
-
content_tag "ol" do
|
89
|
-
object.collect do |i|
|
90
|
-
content_tag "li", present(i, options)
|
91
|
-
end.join.html_safe
|
92
|
-
end
|
93
|
-
|
94
|
-
when Hash
|
95
|
-
# sort by keys
|
96
|
-
content_tag "dl" do
|
97
|
-
object.keys.sort.collect do |k|
|
98
|
-
content_tag("dt", k) +
|
99
|
-
content_tag("dd", present(object[k], options))
|
100
|
-
end.join.html_safe
|
101
|
-
end
|
102
|
-
|
103
|
-
when TrueClass, FalseClass
|
104
|
-
object ? "True" : "False"
|
105
|
-
|
106
|
-
when Date, Time, DateTime
|
107
|
-
l(object, :format => :default)
|
108
|
-
|
109
|
-
else
|
110
|
-
options[:raw] ? object.to_s.html_safe : object.to_s
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
1
|
+
module Presenting
|
2
|
+
module Helpers
|
3
|
+
def presentation_stylesheets(*args)
|
4
|
+
warn "[DEPRECATION] presentation_stylesheets is deprecated. Please use the stylesheets" <<
|
5
|
+
"that are copied to public/stylesheets/presenting/* on boot."
|
6
|
+
stylesheet_link_tag presentation_stylesheet_path(args.sort.join(','), :format => 'css')
|
7
|
+
end
|
8
|
+
|
9
|
+
def presentation_javascript(*args)
|
10
|
+
warn "[DEPRECATION] presentation_javascript is deprecated. Please use the javascripts" <<
|
11
|
+
"that are copied to public/javascripts/presenting/* on boot."
|
12
|
+
javascript_include_tag presentation_javascript_path(args.sort.join(','), :format => 'js')
|
13
|
+
end
|
14
|
+
|
15
|
+
def present(*args, &block)
|
16
|
+
options = args.length > 1 ? args.extract_options! : {}
|
17
|
+
|
18
|
+
if args.first.is_a? Symbol
|
19
|
+
object, presentation = nil, args.first
|
20
|
+
else
|
21
|
+
object, presentation = args.first, args.second
|
22
|
+
end
|
23
|
+
|
24
|
+
if presentation
|
25
|
+
klass = "Presentation::#{presentation.to_s.camelcase}".constantize rescue nil
|
26
|
+
if klass
|
27
|
+
instance = klass.new(options, &block)
|
28
|
+
instance.presentable = object
|
29
|
+
instance.controller = controller
|
30
|
+
instance.render
|
31
|
+
elsif respond_to?(method_name = "present_#{presentation}")
|
32
|
+
send(method_name, object, options)
|
33
|
+
else
|
34
|
+
raise ArgumentError, "unknown presentation `#{presentation}'"
|
35
|
+
end
|
36
|
+
elsif object.respond_to?(:loaded?) # AssociationProxy
|
37
|
+
present_association(object, options)
|
38
|
+
else
|
39
|
+
present_by_class(object, options)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# presents a text search widget for the given field (a Presentation::FieldSearch::Field, probably)
|
44
|
+
def present_text_search(field, options = {})
|
45
|
+
current_value = (params[:search][field.param][:value] rescue nil)
|
46
|
+
text_field_tag options[:name], h(current_value)
|
47
|
+
end
|
48
|
+
|
49
|
+
# presents a checkbox search widget for the given field (a Presentation::FieldSearch::Field, probably)
|
50
|
+
def present_checkbox_search(field, options = {})
|
51
|
+
current_value = (params[:search][field.param][:value] rescue nil)
|
52
|
+
check_box_tag options[:name], '1', current_value.to_s == '1'
|
53
|
+
end
|
54
|
+
|
55
|
+
# presents a dropdown/select search widget for the given field (a Presentation::FieldSearch::Field, probably)
|
56
|
+
def present_dropdown_search(field, options = {})
|
57
|
+
current_value = (params[:search][field.param][:value] rescue nil)
|
58
|
+
select_tag options[:name], options_for_select(normalize_dropdown_options_to_strings(field.options), current_value)
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
# We want to normalize the value elements of the dropdown options to strings so that
|
64
|
+
# they will match against params[:search].
|
65
|
+
#
|
66
|
+
# Need to handle the three different dropdown options formats:
|
67
|
+
# * array of strings
|
68
|
+
# * array of arrays
|
69
|
+
# * hash
|
70
|
+
def normalize_dropdown_options_to_strings(options)
|
71
|
+
options.to_a.map do |element|
|
72
|
+
if element.is_a? String
|
73
|
+
[element, element]
|
74
|
+
else
|
75
|
+
[element.first, element.last.to_s]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO: special handling for associations (displaying activerecords)
|
81
|
+
def present_association(object, options = {})
|
82
|
+
present_by_class(object, options)
|
83
|
+
end
|
84
|
+
|
85
|
+
def present_by_class(object, options = {})
|
86
|
+
case object
|
87
|
+
when Array
|
88
|
+
content_tag "ol" do
|
89
|
+
object.collect do |i|
|
90
|
+
content_tag "li", present(i, options)
|
91
|
+
end.join.html_safe
|
92
|
+
end
|
93
|
+
|
94
|
+
when Hash
|
95
|
+
# sort by keys
|
96
|
+
content_tag "dl" do
|
97
|
+
object.keys.sort.collect do |k|
|
98
|
+
content_tag("dt", k) +
|
99
|
+
content_tag("dd", present(object[k], options))
|
100
|
+
end.join.html_safe
|
101
|
+
end
|
102
|
+
|
103
|
+
when TrueClass, FalseClass
|
104
|
+
object ? "True" : "False"
|
105
|
+
|
106
|
+
when Date, Time, DateTime
|
107
|
+
l(object, :format => :default)
|
108
|
+
|
109
|
+
else
|
110
|
+
options[:raw] ? object.to_s.html_safe : object.to_s
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
data/lib/presenting/sanitize.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
module Presenting::Sanitize
|
2
|
-
class << self
|
3
|
-
include ERB::Util
|
4
|
-
|
5
|
-
# escape but preserve Arrays and Hashes
|
6
|
-
def h(val)
|
7
|
-
case val
|
8
|
-
when Array
|
9
|
-
val.map{|i| h(i)}
|
10
|
-
|
11
|
-
when Hash
|
12
|
-
val.clone.each{|k, v| val[h(k)] = h(v)}
|
13
|
-
|
14
|
-
else
|
15
|
-
html_escape(val)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
1
|
+
module Presenting::Sanitize
|
2
|
+
class << self
|
3
|
+
include ERB::Util
|
4
|
+
|
5
|
+
# escape but preserve Arrays and Hashes
|
6
|
+
def h(val)
|
7
|
+
case val
|
8
|
+
when Array
|
9
|
+
val.map{|i| h(i)}
|
10
|
+
|
11
|
+
when Hash
|
12
|
+
val.clone.each{|k, v| val[h(k)] = h(v)}
|
13
|
+
|
14
|
+
else
|
15
|
+
html_escape(val)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|