halorgium-actionpack 3.0.pre

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 (154) hide show
  1. data/CHANGELOG +5179 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +409 -0
  4. data/lib/abstract_controller.rb +16 -0
  5. data/lib/abstract_controller/base.rb +158 -0
  6. data/lib/abstract_controller/callbacks.rb +113 -0
  7. data/lib/abstract_controller/exceptions.rb +12 -0
  8. data/lib/abstract_controller/helpers.rb +151 -0
  9. data/lib/abstract_controller/layouts.rb +250 -0
  10. data/lib/abstract_controller/localized_cache.rb +49 -0
  11. data/lib/abstract_controller/logger.rb +61 -0
  12. data/lib/abstract_controller/rendering_controller.rb +188 -0
  13. data/lib/action_controller.rb +72 -0
  14. data/lib/action_controller/base.rb +168 -0
  15. data/lib/action_controller/caching.rb +80 -0
  16. data/lib/action_controller/caching/actions.rb +163 -0
  17. data/lib/action_controller/caching/fragments.rb +116 -0
  18. data/lib/action_controller/caching/pages.rb +154 -0
  19. data/lib/action_controller/caching/sweeping.rb +97 -0
  20. data/lib/action_controller/deprecated.rb +4 -0
  21. data/lib/action_controller/deprecated/integration_test.rb +2 -0
  22. data/lib/action_controller/deprecated/performance_test.rb +1 -0
  23. data/lib/action_controller/dispatch/dispatcher.rb +57 -0
  24. data/lib/action_controller/metal.rb +129 -0
  25. data/lib/action_controller/metal/benchmarking.rb +73 -0
  26. data/lib/action_controller/metal/compatibility.rb +145 -0
  27. data/lib/action_controller/metal/conditional_get.rb +86 -0
  28. data/lib/action_controller/metal/configuration.rb +28 -0
  29. data/lib/action_controller/metal/cookies.rb +105 -0
  30. data/lib/action_controller/metal/exceptions.rb +55 -0
  31. data/lib/action_controller/metal/filter_parameter_logging.rb +77 -0
  32. data/lib/action_controller/metal/flash.rb +162 -0
  33. data/lib/action_controller/metal/head.rb +27 -0
  34. data/lib/action_controller/metal/helpers.rb +115 -0
  35. data/lib/action_controller/metal/hide_actions.rb +47 -0
  36. data/lib/action_controller/metal/http_authentication.rb +312 -0
  37. data/lib/action_controller/metal/layouts.rb +171 -0
  38. data/lib/action_controller/metal/mime_responds.rb +317 -0
  39. data/lib/action_controller/metal/rack_convenience.rb +27 -0
  40. data/lib/action_controller/metal/redirector.rb +22 -0
  41. data/lib/action_controller/metal/render_options.rb +103 -0
  42. data/lib/action_controller/metal/rendering_controller.rb +57 -0
  43. data/lib/action_controller/metal/request_forgery_protection.rb +108 -0
  44. data/lib/action_controller/metal/rescuable.rb +13 -0
  45. data/lib/action_controller/metal/responder.rb +200 -0
  46. data/lib/action_controller/metal/session.rb +15 -0
  47. data/lib/action_controller/metal/session_management.rb +45 -0
  48. data/lib/action_controller/metal/streaming.rb +188 -0
  49. data/lib/action_controller/metal/testing.rb +39 -0
  50. data/lib/action_controller/metal/url_for.rb +41 -0
  51. data/lib/action_controller/metal/verification.rb +130 -0
  52. data/lib/action_controller/middleware.rb +38 -0
  53. data/lib/action_controller/notifications.rb +10 -0
  54. data/lib/action_controller/polymorphic_routes.rb +183 -0
  55. data/lib/action_controller/record_identifier.rb +91 -0
  56. data/lib/action_controller/testing/process.rb +111 -0
  57. data/lib/action_controller/testing/test_case.rb +345 -0
  58. data/lib/action_controller/translation.rb +13 -0
  59. data/lib/action_controller/url_rewriter.rb +204 -0
  60. data/lib/action_controller/vendor/html-scanner.rb +16 -0
  61. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  62. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  63. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +176 -0
  64. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  65. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  66. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  67. data/lib/action_dispatch.rb +70 -0
  68. data/lib/action_dispatch/http/headers.rb +33 -0
  69. data/lib/action_dispatch/http/mime_type.rb +231 -0
  70. data/lib/action_dispatch/http/mime_types.rb +23 -0
  71. data/lib/action_dispatch/http/request.rb +539 -0
  72. data/lib/action_dispatch/http/response.rb +290 -0
  73. data/lib/action_dispatch/http/status_codes.rb +42 -0
  74. data/lib/action_dispatch/http/utils.rb +20 -0
  75. data/lib/action_dispatch/middleware/callbacks.rb +50 -0
  76. data/lib/action_dispatch/middleware/params_parser.rb +79 -0
  77. data/lib/action_dispatch/middleware/rescue.rb +26 -0
  78. data/lib/action_dispatch/middleware/session/abstract_store.rb +208 -0
  79. data/lib/action_dispatch/middleware/session/cookie_store.rb +235 -0
  80. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +47 -0
  81. data/lib/action_dispatch/middleware/show_exceptions.rb +143 -0
  82. data/lib/action_dispatch/middleware/stack.rb +116 -0
  83. data/lib/action_dispatch/middleware/static.rb +44 -0
  84. data/lib/action_dispatch/middleware/string_coercion.rb +29 -0
  85. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +24 -0
  86. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +26 -0
  87. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +10 -0
  88. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +29 -0
  89. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +2 -0
  90. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +10 -0
  91. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +21 -0
  92. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +2 -0
  93. data/lib/action_dispatch/routing.rb +381 -0
  94. data/lib/action_dispatch/routing/deprecated_mapper.rb +878 -0
  95. data/lib/action_dispatch/routing/mapper.rb +327 -0
  96. data/lib/action_dispatch/routing/route.rb +49 -0
  97. data/lib/action_dispatch/routing/route_set.rb +497 -0
  98. data/lib/action_dispatch/testing/assertions.rb +8 -0
  99. data/lib/action_dispatch/testing/assertions/dom.rb +35 -0
  100. data/lib/action_dispatch/testing/assertions/model.rb +19 -0
  101. data/lib/action_dispatch/testing/assertions/response.rb +145 -0
  102. data/lib/action_dispatch/testing/assertions/routing.rb +144 -0
  103. data/lib/action_dispatch/testing/assertions/selector.rb +639 -0
  104. data/lib/action_dispatch/testing/assertions/tag.rb +123 -0
  105. data/lib/action_dispatch/testing/integration.rb +504 -0
  106. data/lib/action_dispatch/testing/performance_test.rb +15 -0
  107. data/lib/action_dispatch/testing/test_request.rb +83 -0
  108. data/lib/action_dispatch/testing/test_response.rb +131 -0
  109. data/lib/action_pack.rb +24 -0
  110. data/lib/action_pack/version.rb +9 -0
  111. data/lib/action_view.rb +58 -0
  112. data/lib/action_view/base.rb +308 -0
  113. data/lib/action_view/context.rb +44 -0
  114. data/lib/action_view/erb/util.rb +48 -0
  115. data/lib/action_view/helpers.rb +62 -0
  116. data/lib/action_view/helpers/active_model_helper.rb +306 -0
  117. data/lib/action_view/helpers/ajax_helper.rb +68 -0
  118. data/lib/action_view/helpers/asset_tag_helper.rb +830 -0
  119. data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
  120. data/lib/action_view/helpers/cache_helper.rb +39 -0
  121. data/lib/action_view/helpers/capture_helper.rb +168 -0
  122. data/lib/action_view/helpers/date_helper.rb +988 -0
  123. data/lib/action_view/helpers/debug_helper.rb +38 -0
  124. data/lib/action_view/helpers/form_helper.rb +1102 -0
  125. data/lib/action_view/helpers/form_options_helper.rb +600 -0
  126. data/lib/action_view/helpers/form_tag_helper.rb +495 -0
  127. data/lib/action_view/helpers/javascript_helper.rb +208 -0
  128. data/lib/action_view/helpers/number_helper.rb +311 -0
  129. data/lib/action_view/helpers/prototype_helper.rb +1309 -0
  130. data/lib/action_view/helpers/raw_output_helper.rb +9 -0
  131. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  132. data/lib/action_view/helpers/record_tag_helper.rb +58 -0
  133. data/lib/action_view/helpers/sanitize_helper.rb +259 -0
  134. data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
  135. data/lib/action_view/helpers/tag_helper.rb +151 -0
  136. data/lib/action_view/helpers/text_helper.rb +594 -0
  137. data/lib/action_view/helpers/translation_helper.rb +39 -0
  138. data/lib/action_view/helpers/url_helper.rb +639 -0
  139. data/lib/action_view/locale/en.yml +117 -0
  140. data/lib/action_view/paths.rb +80 -0
  141. data/lib/action_view/render/partials.rb +342 -0
  142. data/lib/action_view/render/rendering.rb +134 -0
  143. data/lib/action_view/safe_buffer.rb +28 -0
  144. data/lib/action_view/template/error.rb +101 -0
  145. data/lib/action_view/template/handler.rb +36 -0
  146. data/lib/action_view/template/handlers.rb +52 -0
  147. data/lib/action_view/template/handlers/builder.rb +17 -0
  148. data/lib/action_view/template/handlers/erb.rb +53 -0
  149. data/lib/action_view/template/handlers/rjs.rb +18 -0
  150. data/lib/action_view/template/resolver.rb +165 -0
  151. data/lib/action_view/template/template.rb +131 -0
  152. data/lib/action_view/template/text.rb +38 -0
  153. data/lib/action_view/test_case.rb +163 -0
  154. metadata +236 -0
@@ -0,0 +1,44 @@
1
+ module ActionView
2
+ module CompiledTemplates #:nodoc:
3
+ # holds compiled template code
4
+ end
5
+
6
+ # ActionView contexts are supplied to ActionController
7
+ # to render template. The default ActionView context
8
+ # is ActionView::Base.
9
+ #
10
+ # In order to work with ActionController, a Context
11
+ # must implement:
12
+ #
13
+ # Context.for_controller[controller] Create a new ActionView instance for a
14
+ # controller
15
+ # Context#render_partial[options]
16
+ # - responsible for setting options[:_template]
17
+ # - Returns String with the rendered partial
18
+ # options<Hash>:: see _render_partial in ActionView::Base
19
+ # Context#render_template[template, layout, options, partial]
20
+ # - Returns String with the rendered template
21
+ # template<ActionView::Template>:: The template to render
22
+ # layout<ActionView::Template>:: The layout to render around the template
23
+ # options<Hash>:: See _render_template_with_layout in ActionView::Base
24
+ # partial<Boolean>:: Whether or not the template to render is a partial
25
+ #
26
+ # An ActionView context can also mix in ActionView's
27
+ # helpers. In order to mix in helpers, a context must
28
+ # implement:
29
+ #
30
+ # Context#controller
31
+ # - Returns an instance of AbstractController
32
+ #
33
+ # In any case, a context must mix in ActionView::Context,
34
+ # which stores compiled template and provides the output
35
+ # buffer.
36
+ module Context
37
+ include CompiledTemplates
38
+ attr_accessor :output_buffer
39
+
40
+ def convert_to_model(object)
41
+ object.respond_to?(:to_model) ? object.to_model : object
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ require 'erb'
2
+
3
+ class ERB
4
+ module Util
5
+ HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;' }
6
+ JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' }
7
+
8
+ # A utility method for escaping HTML tag characters.
9
+ # This method is also aliased as <tt>h</tt>.
10
+ #
11
+ # In your ERb templates, use this method to escape any unsafe content. For example:
12
+ # <%=h @person.name %>
13
+ #
14
+ # ==== Example:
15
+ # puts html_escape("is a > 0 & a < 10?")
16
+ # # => is a &gt; 0 &amp; a &lt; 10?
17
+ def html_escape(s)
18
+ s = s.to_s
19
+ if s.html_safe?
20
+ s
21
+ else
22
+ s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }.html_safe!
23
+ end
24
+ end
25
+
26
+ alias h html_escape
27
+
28
+ module_function :html_escape
29
+ module_function :h
30
+
31
+ # A utility method for escaping HTML entities in JSON strings.
32
+ # This method is also aliased as <tt>j</tt>.
33
+ #
34
+ # In your ERb templates, use this method to escape any HTML entities:
35
+ # <%=j @person.to_json %>
36
+ #
37
+ # ==== Example:
38
+ # puts json_escape("is a > 0 & a < 10?")
39
+ # # => is a \u003E 0 \u0026 a \u003C 10?
40
+ def json_escape(s)
41
+ s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
42
+ end
43
+
44
+ alias j json_escape
45
+ module_function :j
46
+ module_function :json_escape
47
+ end
48
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_support/benchmarkable'
2
+
3
+ module ActionView #:nodoc:
4
+ module Helpers #:nodoc:
5
+ autoload :ActiveModelHelper, 'action_view/helpers/active_model_helper'
6
+ autoload :AjaxHelper, 'action_view/helpers/ajax_helper'
7
+ autoload :AssetTagHelper, 'action_view/helpers/asset_tag_helper'
8
+ autoload :AtomFeedHelper, 'action_view/helpers/atom_feed_helper'
9
+ autoload :CacheHelper, 'action_view/helpers/cache_helper'
10
+ autoload :CaptureHelper, 'action_view/helpers/capture_helper'
11
+ autoload :DateHelper, 'action_view/helpers/date_helper'
12
+ autoload :DebugHelper, 'action_view/helpers/debug_helper'
13
+ autoload :FormHelper, 'action_view/helpers/form_helper'
14
+ autoload :FormOptionsHelper, 'action_view/helpers/form_options_helper'
15
+ autoload :FormTagHelper, 'action_view/helpers/form_tag_helper'
16
+ autoload :JavaScriptHelper, 'action_view/helpers/javascript_helper'
17
+ autoload :NumberHelper, 'action_view/helpers/number_helper'
18
+ autoload :PrototypeHelper, 'action_view/helpers/prototype_helper'
19
+ autoload :RawOutputHelper, 'action_view/helpers/raw_output_helper'
20
+ autoload :RecordIdentificationHelper, 'action_view/helpers/record_identification_helper'
21
+ autoload :RecordTagHelper, 'action_view/helpers/record_tag_helper'
22
+ autoload :SanitizeHelper, 'action_view/helpers/sanitize_helper'
23
+ autoload :ScriptaculousHelper, 'action_view/helpers/scriptaculous_helper'
24
+ autoload :TagHelper, 'action_view/helpers/tag_helper'
25
+ autoload :TextHelper, 'action_view/helpers/text_helper'
26
+ autoload :TranslationHelper, 'action_view/helpers/translation_helper'
27
+ autoload :UrlHelper, 'action_view/helpers/url_helper'
28
+
29
+ def self.included(base)
30
+ base.extend(ClassMethods)
31
+ end
32
+
33
+ module ClassMethods
34
+ include SanitizeHelper::ClassMethods
35
+ end
36
+
37
+ include ActiveSupport::Benchmarkable
38
+
39
+ include ActiveModelHelper
40
+ include AssetTagHelper
41
+ include AtomFeedHelper
42
+ include CacheHelper
43
+ include CaptureHelper
44
+ include DateHelper
45
+ include DebugHelper
46
+ include FormHelper
47
+ include FormOptionsHelper
48
+ include FormTagHelper
49
+ include JavaScriptHelper
50
+ include NumberHelper
51
+ include PrototypeHelper
52
+ include RawOutputHelper
53
+ include RecordIdentificationHelper
54
+ include RecordTagHelper
55
+ include SanitizeHelper
56
+ include ScriptaculousHelper
57
+ include TagHelper
58
+ include TextHelper
59
+ include TranslationHelper
60
+ include UrlHelper
61
+ end
62
+ end
@@ -0,0 +1,306 @@
1
+ require 'cgi'
2
+ require 'action_view/helpers/form_helper'
3
+ require 'active_support/core_ext/class/attribute_accessors'
4
+ require 'active_support/core_ext/enumerable'
5
+ require 'active_support/core_ext/kernel/reporting'
6
+
7
+ module ActionView
8
+ class Base
9
+ @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe! }
10
+ cattr_accessor :field_error_proc
11
+ end
12
+
13
+ module Helpers
14
+ # The Active Record Helper makes it easier to create forms for records kept in instance variables. The most far-reaching is the +form+
15
+ # method that creates a complete form for all the basic content types of the record (not associations or aggregations, though). This
16
+ # is a great way of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form.
17
+ # In that case, it's better to use the +input+ method and the specialized +form+ methods in link:classes/ActionView/Helpers/FormHelper.html
18
+ module ActiveModelHelper
19
+ # Returns a default input tag for the type of object returned by the method. For example, if <tt>@post</tt>
20
+ # has an attribute +title+ mapped to a +VARCHAR+ column that holds "Hello World":
21
+ #
22
+ # input("post", "title")
23
+ # # => <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />
24
+ def input(record_name, method, options = {})
25
+ InstanceTag.new(record_name, method, self).to_tag(options)
26
+ end
27
+
28
+ # Returns an entire form with all needed input tags for a specified Active Record object. For example, if <tt>@post</tt>
29
+ # has attributes named +title+ of type +VARCHAR+ and +body+ of type +TEXT+ then
30
+ #
31
+ # form("post")
32
+ #
33
+ # would yield a form like the following (modulus formatting):
34
+ #
35
+ # <form action='/posts/create' method='post'>
36
+ # <p>
37
+ # <label for="post_title">Title</label><br />
38
+ # <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />
39
+ # </p>
40
+ # <p>
41
+ # <label for="post_body">Body</label><br />
42
+ # <textarea cols="40" id="post_body" name="post[body]" rows="20"></textarea>
43
+ # </p>
44
+ # <input name="commit" type="submit" value="Create" />
45
+ # </form>
46
+ #
47
+ # It's possible to specialize the form builder by using a different action name and by supplying another
48
+ # block renderer. For example, if <tt>@entry</tt> has an attribute +message+ of type +VARCHAR+ then
49
+ #
50
+ # form("entry",
51
+ # :action => "sign",
52
+ # :input_block => Proc.new { |record, column|
53
+ # "#{column.human_name}: #{input(record, column.name)}<br />"
54
+ # })
55
+ #
56
+ # would yield a form like the following (modulus formatting):
57
+ #
58
+ # <form action="/entries/sign" method="post">
59
+ # Message:
60
+ # <input id="entry_message" name="entry[message]" size="30" type="text" /><br />
61
+ # <input name="commit" type="submit" value="Sign" />
62
+ # </form>
63
+ #
64
+ # It's also possible to add additional content to the form by giving it a block, such as:
65
+ #
66
+ # form("entry", :action => "sign") do |form|
67
+ # form << content_tag("b", "Department")
68
+ # form << collection_select("department", "id", @departments, "id", "name")
69
+ # end
70
+ #
71
+ # The following options are available:
72
+ #
73
+ # * <tt>:action</tt> - The action used when submitting the form (default: +create+ if a new record, otherwise +update+).
74
+ # * <tt>:input_block</tt> - Specialize the output using a different block, see above.
75
+ # * <tt>:method</tt> - The method used when submitting the form (default: +post+).
76
+ # * <tt>:multipart</tt> - Whether to change the enctype of the form to "multipart/form-data", used when uploading a file (default: +false+).
77
+ # * <tt>:submit_value</tt> - The text of the submit button (default: "Create" if a new record, otherwise "Update").
78
+ def form(record_name, options = {})
79
+ record = instance_variable_get("@#{record_name}")
80
+ record = convert_to_model(record)
81
+
82
+ options = options.symbolize_keys
83
+ options[:action] ||= record.new_record? ? "create" : "update"
84
+ action = url_for(:action => options[:action], :id => record)
85
+
86
+ submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize
87
+
88
+ contents = form_tag({:action => action}, :method =>(options[:method] || 'post'), :enctype => options[:multipart] ? 'multipart/form-data': nil)
89
+ contents << hidden_field(record_name, :id) unless record.new_record?
90
+ contents << all_input_tags(record, record_name, options)
91
+ yield contents if block_given?
92
+ contents << submit_tag(submit_value)
93
+ contents << '</form>'
94
+ contents.html_safe!
95
+ end
96
+
97
+ # Returns a string containing the error message attached to the +method+ on the +object+ if one exists.
98
+ # This error message is wrapped in a <tt>DIV</tt> tag, which can be extended to include a <tt>:prepend_text</tt>
99
+ # and/or <tt>:append_text</tt> (to properly explain the error), and a <tt>:css_class</tt> to style it
100
+ # accordingly. +object+ should either be the name of an instance variable or the actual object. The method can be
101
+ # passed in either as a string or a symbol.
102
+ # As an example, let's say you have a model <tt>@post</tt> that has an error message on the +title+ attribute:
103
+ #
104
+ # <%= error_message_on "post", "title" %>
105
+ # # => <div class="formError">can't be empty</div>
106
+ #
107
+ # <%= error_message_on @post, :title %>
108
+ # # => <div class="formError">can't be empty</div>
109
+ #
110
+ # <%= error_message_on "post", "title",
111
+ # :prepend_text => "Title simply ",
112
+ # :append_text => " (or it won't work).",
113
+ # :css_class => "inputError" %>
114
+ def error_message_on(object, method, *args)
115
+ options = args.extract_options!
116
+ unless args.empty?
117
+ ActiveSupport::Deprecation.warn('error_message_on takes an option hash instead of separate ' +
118
+ 'prepend_text, append_text, and css_class arguments', caller)
119
+
120
+ options[:prepend_text] = args[0] || ''
121
+ options[:append_text] = args[1] || ''
122
+ options[:css_class] = args[2] || 'formError'
123
+ end
124
+ options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError')
125
+
126
+ object = convert_to_model(object)
127
+
128
+ if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) &&
129
+ (errors = obj.errors[method])
130
+ content_tag("div",
131
+ "#{options[:prepend_text]}#{ERB::Util.html_escape(errors.first)}#{options[:append_text]}",
132
+ :class => options[:css_class]
133
+ )
134
+ else
135
+ ''
136
+ end
137
+ end
138
+
139
+ # Returns a string with a <tt>DIV</tt> containing all of the error messages for the objects located as instance variables by the names
140
+ # given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are
141
+ # provided.
142
+ #
143
+ # This <tt>DIV</tt> can be tailored by the following options:
144
+ #
145
+ # * <tt>:header_tag</tt> - Used for the header of the error div (default: "h2").
146
+ # * <tt>:id</tt> - The id of the error div (default: "errorExplanation").
147
+ # * <tt>:class</tt> - The class of the error div (default: "errorExplanation").
148
+ # * <tt>:object</tt> - The object (or array of objects) for which to display errors,
149
+ # if you need to escape the instance variable convention.
150
+ # * <tt>:object_name</tt> - The object name to use in the header, or any text that you prefer.
151
+ # If <tt>:object_name</tt> is not set, the name of the first object will be used.
152
+ # * <tt>:header_message</tt> - The message in the header of the error div. Pass +nil+
153
+ # or an empty string to avoid the header message altogether. (Default: "X errors
154
+ # prohibited this object from being saved").
155
+ # * <tt>:message</tt> - The explanation message after the header message and before
156
+ # the error list. Pass +nil+ or an empty string to avoid the explanation message
157
+ # altogether. (Default: "There were problems with the following fields:").
158
+ #
159
+ # To specify the display for one object, you simply provide its name as a parameter.
160
+ # For example, for the <tt>@user</tt> model:
161
+ #
162
+ # error_messages_for 'user'
163
+ #
164
+ # You can also supply an object:
165
+ #
166
+ # error_messages_for @user
167
+ #
168
+ # This will use the last part of the model name in the presentation. For instance, if
169
+ # this is a MyKlass::User object, this will use "user" as the name in the String. This
170
+ # is taken from MyKlass::User.model_name.human, which can be overridden.
171
+ #
172
+ # To specify more than one object, you simply list them; optionally, you can add an extra <tt>:object_name</tt> parameter, which
173
+ # will be the name used in the header message:
174
+ #
175
+ # error_messages_for 'user_common', 'user', :object_name => 'user'
176
+ #
177
+ # You can also use a number of objects, which will have the same naming semantics
178
+ # as a single object.
179
+ #
180
+ # error_messages_for @user, @post
181
+ #
182
+ # If the objects cannot be located as instance variables, you can add an extra <tt>:object</tt> parameter which gives the actual
183
+ # object (or array of objects to use):
184
+ #
185
+ # error_messages_for 'user', :object => @question.user
186
+ #
187
+ # NOTE: This is a pre-packaged presentation of the errors with embedded strings and a certain HTML structure. If what
188
+ # you need is significantly different from the default presentation, it makes plenty of sense to access the <tt>object.errors</tt>
189
+ # instance yourself and set it up. View the source of this method to see how easy it is.
190
+ def error_messages_for(*params)
191
+ options = params.extract_options!.symbolize_keys
192
+
193
+ objects = Array.wrap(options.delete(:object) || params).map do |object|
194
+ object = instance_variable_get("@#{object}") unless object.respond_to?(:to_model)
195
+ object = convert_to_model(object)
196
+
197
+ if object.class.respond_to?(:model_name)
198
+ options[:object_name] ||= object.class.model_name.human.downcase
199
+ end
200
+
201
+ object
202
+ end
203
+
204
+ objects.compact!
205
+ count = objects.inject(0) {|sum, object| sum + object.errors.count }
206
+
207
+ unless count.zero?
208
+ html = {}
209
+ [:id, :class].each do |key|
210
+ if options.include?(key)
211
+ value = options[key]
212
+ html[key] = value unless value.blank?
213
+ else
214
+ html[key] = 'errorExplanation'
215
+ end
216
+ end
217
+ options[:object_name] ||= params.first
218
+
219
+ I18n.with_options :locale => options[:locale], :scope => [:activemodel, :errors, :template] do |locale|
220
+ header_message = if options.include?(:header_message)
221
+ options[:header_message]
222
+ else
223
+ locale.t :header, :count => count, :model => options[:object_name].to_s.gsub('_', ' ')
224
+ end
225
+
226
+ message = options.include?(:message) ? options[:message] : locale.t(:body)
227
+
228
+ error_messages = objects.sum do |object|
229
+ object.errors.full_messages.map do |msg|
230
+ content_tag(:li, ERB::Util.html_escape(msg))
231
+ end
232
+ end.join
233
+
234
+ contents = ''
235
+ contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
236
+ contents << content_tag(:p, message) unless message.blank?
237
+ contents << content_tag(:ul, error_messages)
238
+
239
+ content_tag(:div, contents, html)
240
+ end
241
+ else
242
+ ''
243
+ end
244
+ end
245
+
246
+ private
247
+ def all_input_tags(record, record_name, options)
248
+ input_block = options[:input_block] || default_input_block
249
+ record.class.content_columns.collect{ |column| input_block.call(record_name, column) }.join("\n")
250
+ end
251
+
252
+ def default_input_block
253
+ Proc.new { |record, column| %(<p><label for="#{record}_#{column.name}">#{column.human_name}</label><br />#{input(record, column.name)}</p>) }
254
+ end
255
+ end
256
+
257
+ module ActiveRecordInstanceTag
258
+ def object
259
+ @active_model_object ||= begin
260
+ object = super
261
+ object.respond_to?(:to_model) ? object.to_model : object
262
+ end
263
+ end
264
+
265
+ def to_tag(options = {})
266
+ case column_type
267
+ when :string
268
+ field_type = @method_name.include?("password") ? "password" : "text"
269
+ to_input_field_tag(field_type, options)
270
+ when :text
271
+ to_text_area_tag(options)
272
+ when :integer, :float, :decimal
273
+ to_input_field_tag("text", options)
274
+ when :date
275
+ to_date_select_tag(options)
276
+ when :datetime, :timestamp
277
+ to_datetime_select_tag(options)
278
+ when :time
279
+ to_time_select_tag(options)
280
+ when :boolean
281
+ to_boolean_select_tag(options)
282
+ end
283
+ end
284
+
285
+ %w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth|
286
+ module_eval "def #{meth}(*) error_wrapping(super) end"
287
+ end
288
+
289
+ def error_wrapping(html_tag)
290
+ if object.respond_to?(:errors) && object.errors.respond_to?(:full_messages) && object.errors[@method_name].any?
291
+ Base.field_error_proc.call(html_tag, self)
292
+ else
293
+ html_tag
294
+ end
295
+ end
296
+
297
+ def column_type
298
+ object.send(:column_for_attribute, @method_name).type
299
+ end
300
+ end
301
+
302
+ class InstanceTag
303
+ include ActiveRecordInstanceTag
304
+ end
305
+ end
306
+ end