presenting 2.0.0 → 2.0.1

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