presenting 2.0.0 → 2.0.1

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 (63) hide show
  1. data/LICENSE +20 -20
  2. data/README +10 -10
  3. data/Rakefile +22 -22
  4. data/app/assets/javascripts/search.js +13 -13
  5. data/app/assets/stylesheets/details-color.css +7 -7
  6. data/app/assets/stylesheets/details.css +10 -10
  7. data/app/assets/stylesheets/form.css +1 -1
  8. data/app/assets/stylesheets/grid-color.css +71 -71
  9. data/app/assets/stylesheets/grid.css +64 -64
  10. data/app/assets/stylesheets/search-color.css +16 -16
  11. data/app/assets/stylesheets/search.css +45 -45
  12. data/app/controllers/presentation/assets_controller.rb +42 -42
  13. data/app/views/presentations/_details.erb +11 -11
  14. data/app/views/presentations/_field_search.erb +14 -14
  15. data/app/views/presentations/_form.erb +20 -20
  16. data/app/views/presentations/_grid.erb +70 -70
  17. data/app/views/presentations/_search.erb +7 -7
  18. data/lib/presentation/base.rb +31 -31
  19. data/lib/presentation/details.rb +21 -21
  20. data/lib/presentation/field_search.rb +67 -67
  21. data/lib/presentation/form.rb +149 -149
  22. data/lib/presentation/grid.rb +162 -160
  23. data/lib/presentation/search.rb +9 -9
  24. data/lib/presenting/attribute.rb +51 -51
  25. data/lib/presenting/configurable.rb +10 -10
  26. data/lib/presenting/defaults.rb +10 -10
  27. data/lib/presenting/field_set.rb +26 -26
  28. data/lib/presenting/form_helpers.rb +51 -51
  29. data/lib/presenting/helpers.rb +114 -114
  30. data/lib/presenting/sanitize.rb +19 -19
  31. data/lib/presenting/search.rb +185 -185
  32. data/lib/presenting/sorting.rb +87 -87
  33. data/test/attribute_test.rb +61 -61
  34. data/test/configurable_test.rb +20 -20
  35. data/test/details_test.rb +68 -68
  36. data/test/field_search_test.rb +102 -102
  37. data/test/field_set_test.rb +46 -46
  38. data/test/grid_test.rb +246 -239
  39. data/test/helpers_test.rb +72 -72
  40. data/test/presenting_test.rb +15 -15
  41. data/test/r3/Gemfile +7 -7
  42. data/test/r3/Gemfile.lock +86 -82
  43. data/test/r3/config/application.rb +12 -12
  44. data/test/r3/config/boot.rb +6 -6
  45. data/test/r3/config/database.yml +22 -22
  46. data/test/r3/config/environment.rb +5 -5
  47. data/test/r3/config/environments/test.rb +35 -35
  48. data/test/r3/db/test.sqlite3 +0 -0
  49. data/test/r3/log/test.log +336 -0
  50. data/test/r3/public/javascripts/presenting/grid.js +0 -0
  51. data/test/r3/public/javascripts/presenting/search.js +13 -13
  52. data/test/r3/public/stylesheets/presenting/details-color.css +7 -7
  53. data/test/r3/public/stylesheets/presenting/details.css +10 -10
  54. data/test/r3/public/stylesheets/presenting/form.css +1 -1
  55. data/test/r3/public/stylesheets/presenting/grid-color.css +71 -71
  56. data/test/r3/public/stylesheets/presenting/grid.css +64 -64
  57. data/test/r3/public/stylesheets/presenting/search-color.css +16 -16
  58. data/test/r3/public/stylesheets/presenting/search.css +45 -45
  59. data/test/sanitize_test.rb +15 -15
  60. data/test/search_conditions_test.rb +137 -137
  61. data/test/search_test.rb +30 -30
  62. data/test/sorting_test.rb +63 -63
  63. metadata +74 -74
@@ -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
@@ -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
+
@@ -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
@@ -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
@@ -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