nuatt-formtastic 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.textile +635 -0
  3. data/lib/formtastic.rb +24 -0
  4. data/lib/formtastic/form_builder.rb +75 -0
  5. data/lib/formtastic/helpers.rb +15 -0
  6. data/lib/formtastic/helpers/buttons_helper.rb +277 -0
  7. data/lib/formtastic/helpers/errors_helper.rb +124 -0
  8. data/lib/formtastic/helpers/fieldset_wrapper.rb +62 -0
  9. data/lib/formtastic/helpers/file_column_detection.rb +16 -0
  10. data/lib/formtastic/helpers/form_helper.rb +221 -0
  11. data/lib/formtastic/helpers/input_helper.rb +357 -0
  12. data/lib/formtastic/helpers/inputs_helper.rb +381 -0
  13. data/lib/formtastic/helpers/reflection.rb +12 -0
  14. data/lib/formtastic/helpers/semantic_form_helper.rb +11 -0
  15. data/lib/formtastic/html_attributes.rb +21 -0
  16. data/lib/formtastic/i18n.rb +32 -0
  17. data/lib/formtastic/inputs.rb +29 -0
  18. data/lib/formtastic/inputs/base.rb +50 -0
  19. data/lib/formtastic/inputs/base/associations.rb +33 -0
  20. data/lib/formtastic/inputs/base/choices.rb +88 -0
  21. data/lib/formtastic/inputs/base/collections.rb +94 -0
  22. data/lib/formtastic/inputs/base/database.rb +17 -0
  23. data/lib/formtastic/inputs/base/errors.rb +58 -0
  24. data/lib/formtastic/inputs/base/fileish.rb +23 -0
  25. data/lib/formtastic/inputs/base/grouped_collections.rb +77 -0
  26. data/lib/formtastic/inputs/base/hints.rb +31 -0
  27. data/lib/formtastic/inputs/base/html.rb +51 -0
  28. data/lib/formtastic/inputs/base/labelling.rb +53 -0
  29. data/lib/formtastic/inputs/base/naming.rb +54 -0
  30. data/lib/formtastic/inputs/base/options.rb +18 -0
  31. data/lib/formtastic/inputs/base/stringish.rb +30 -0
  32. data/lib/formtastic/inputs/base/timeish.rb +125 -0
  33. data/lib/formtastic/inputs/base/validations.rb +125 -0
  34. data/lib/formtastic/inputs/base/wrapping.rb +38 -0
  35. data/lib/formtastic/inputs/boolean_input.rb +87 -0
  36. data/lib/formtastic/inputs/check_boxes_input.rb +169 -0
  37. data/lib/formtastic/inputs/country_input.rb +66 -0
  38. data/lib/formtastic/inputs/date_input.rb +14 -0
  39. data/lib/formtastic/inputs/datetime_input.rb +9 -0
  40. data/lib/formtastic/inputs/email_input.rb +40 -0
  41. data/lib/formtastic/inputs/file_input.rb +42 -0
  42. data/lib/formtastic/inputs/hidden_input.rb +66 -0
  43. data/lib/formtastic/inputs/number_input.rb +72 -0
  44. data/lib/formtastic/inputs/numeric_input.rb +20 -0
  45. data/lib/formtastic/inputs/password_input.rb +40 -0
  46. data/lib/formtastic/inputs/phone_input.rb +41 -0
  47. data/lib/formtastic/inputs/radio_input.rb +146 -0
  48. data/lib/formtastic/inputs/search_input.rb +40 -0
  49. data/lib/formtastic/inputs/select_input.rb +208 -0
  50. data/lib/formtastic/inputs/string_input.rb +34 -0
  51. data/lib/formtastic/inputs/text_input.rb +47 -0
  52. data/lib/formtastic/inputs/time_input.rb +14 -0
  53. data/lib/formtastic/inputs/time_zone_input.rb +48 -0
  54. data/lib/formtastic/inputs/url_input.rb +40 -0
  55. data/lib/formtastic/localized_string.rb +96 -0
  56. data/lib/formtastic/railtie.rb +12 -0
  57. data/lib/formtastic/semantic_form_builder.rb +11 -0
  58. data/lib/formtastic/util.rb +25 -0
  59. data/lib/generators/formtastic/form/form_generator.rb +95 -0
  60. data/lib/generators/formtastic/install/install_generator.rb +23 -0
  61. data/lib/generators/templates/_form.html.erb +7 -0
  62. data/lib/generators/templates/_form.html.haml +5 -0
  63. data/lib/generators/templates/formtastic.css +145 -0
  64. data/lib/generators/templates/formtastic.rb +74 -0
  65. data/lib/generators/templates/formtastic_changes.css +14 -0
  66. data/lib/locale/en.yml +7 -0
  67. data/lib/tasks/verify_rcov.rb +44 -0
  68. metadata +206 -19
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ require 'formtastic/railtie.rb' if defined?(Rails)
3
+
4
+ module Formtastic
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :FormBuilder
8
+ autoload :SemanticFormBuilder
9
+ autoload :Helpers
10
+ autoload :HtmlAttributes
11
+ autoload :I18n
12
+ autoload :Inputs
13
+ autoload :LocalizedString
14
+ autoload :Util
15
+
16
+ # @private
17
+ class UnknownInputError < NameError
18
+ end
19
+
20
+ # @private
21
+ class PolymorphicInputWithoutCollectionError < ArgumentError
22
+ end
23
+
24
+ end
@@ -0,0 +1,75 @@
1
+ module Formtastic
2
+ class FormBuilder < ActionView::Helpers::FormBuilder
3
+
4
+ def self.configure(name, value = nil)
5
+ class_attribute(name)
6
+ self.send(:"#{name}=", value)
7
+ end
8
+
9
+ configure :custom_namespace
10
+ configure :default_text_field_size
11
+ configure :default_text_area_height, 20
12
+ configure :default_text_area_width
13
+ configure :all_fields_required_by_default, true
14
+ configure :include_blank_for_select_by_default, true
15
+ configure :required_string, proc { Formtastic::Util.html_safe(%{<abbr title="#{Formtastic::I18n.t(:required)}">*</abbr>}) }
16
+ configure :optional_string, ''
17
+ configure :inline_errors, :sentence
18
+ configure :label_str_method, :humanize
19
+ configure :collection_label_methods, %w[to_label display_name full_name name title username login value to_s]
20
+ configure :collection_value_methods, %w[id to_s]
21
+ configure :custom_inline_order, {}
22
+ configure :file_methods, [ :file?, :public_filename, :filename ]
23
+ configure :file_metadata_suffixes, ['content_type', 'file_name', 'file_size']
24
+ configure :priority_countries, ["Australia", "Canada", "United Kingdom", "United States"]
25
+ configure :i18n_lookups_by_default, true
26
+ configure :escape_html_entities_in_hints_and_labels, true
27
+ configure :default_commit_button_accesskey
28
+ configure :default_inline_error_class, 'inline-errors'
29
+ configure :default_error_list_class, 'errors'
30
+ configure :default_hint_class, 'inline-hints'
31
+
32
+ attr_reader :template
33
+
34
+ attr_reader :auto_index
35
+
36
+ include Formtastic::HtmlAttributes
37
+
38
+ include Formtastic::Helpers::InputHelper
39
+ include Formtastic::Helpers::InputsHelper
40
+ include Formtastic::Helpers::ButtonsHelper
41
+ include Formtastic::Helpers::ErrorsHelper
42
+
43
+ # A thin wrapper around `ActionView::Helpers::FormBuilder#fields_for` helper to set
44
+ # `:builder => Formtastic::FormBuilder` for nesting forms inside the builder. Can be used in
45
+ # the same way, but you'll also have access to the helpers in `Formtastic::FormBuilder`
46
+ # (such as {#input}, etc) inside the block.
47
+ #
48
+ # @see http://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-fields_for ActionView::Helpers::FormBuilder#fields_for
49
+ # @see http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for ActionView::Helpers::FormHelper#fields_for
50
+ # @see Formtastic::Helpers::FormHelper#semantic_fields_for
51
+ #
52
+ # @example
53
+ # <% semantic_form_for @post do |post| %>
54
+ # <% post.semantic_fields_for :author do |author| %>
55
+ # <% author.inputs :name %>
56
+ # <% end %>
57
+ # <% end %>
58
+ #
59
+ # <form ...>
60
+ # <fieldset class="inputs">
61
+ # <ol>
62
+ # <li class="string"><input type='text' name='post[author][name]' id='post_author_name' /></li>
63
+ # </ol>
64
+ # </fieldset>
65
+ # </form>
66
+ def semantic_fields_for(record_or_name_or_array, *args, &block)
67
+ opts = args.extract_options!
68
+ opts[:builder] ||= self.class
69
+ args.push(opts)
70
+ fields_for(record_or_name_or_array, *args, &block)
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,15 @@
1
+ module Formtastic
2
+ # @private
3
+ module Helpers
4
+ autoload :ButtonsHelper, 'formtastic/helpers/buttons_helper'
5
+ autoload :ErrorsHelper, 'formtastic/helpers/errors_helper'
6
+ autoload :FieldsetWrapper, 'formtastic/helpers/fieldset_wrapper'
7
+ autoload :FileColumnDetection, 'formtastic/helpers/file_column_detection'
8
+ autoload :FormHelper, 'formtastic/helpers/form_helper'
9
+ autoload :InputHelper, 'formtastic/helpers/input_helper'
10
+ autoload :InputsHelper, 'formtastic/helpers/inputs_helper'
11
+ autoload :LabelHelper, 'formtastic/helpers/label_helper'
12
+ autoload :SemanticFormHelper, 'formtastic/helpers/semantic_form_helper'
13
+ autoload :Reflection, 'formtastic/helpers/reflection'
14
+ end
15
+ end
@@ -0,0 +1,277 @@
1
+ module Formtastic
2
+ module Helpers
3
+
4
+ # ButtonsHelper encapsulates the responsibilties of the {#buttons} and {#commit_button} helpers
5
+ # for submitting forms.
6
+ #
7
+ # {#buttons} is used to wrap the form's button(s) and actions in a `<fieldset>` and `<ol>`,
8
+ # with each item in the list containing the markup representing a single button.
9
+ #
10
+ # {#buttons} is usually called with a block containing a single {#commit_button} call:
11
+ #
12
+ # <%= semantic_form_for @post do |f| %>
13
+ # ...
14
+ # <%= f.buttons do %>
15
+ # <%= f.commit_button
16
+ # <% end %>
17
+ # <% end %>
18
+ #
19
+ # The HTML output will be something like:
20
+ #
21
+ # <form class="formtastic" method="post" action="...">
22
+ # ...
23
+ # <fieldset class="buttons">
24
+ # <ol>
25
+ # <li class="commit">
26
+ # <input type="submit" name="commit" value="Create Post" class="create">
27
+ # </li>
28
+ # </ol>
29
+ # </fieldset>
30
+ # </form>
31
+ #
32
+ # While this may seem slightly over-engineered, it is consistent with the way form inputs are
33
+ # handled, and makes room for other types of buttons and actions in future versions (such as
34
+ # cancel buttons or links, reset buttons and even alternate actions like 'save and continue
35
+ # editing').
36
+ #
37
+ # It's important to note that the `semantic_form_for` and {#buttons} blocks wrap the
38
+ # standard Rails `form_for` helper and form builder, so you have full access to every standard
39
+ # Rails form helper, with any HTML markup and ERB syntax, allowing you to "break free" from
40
+ # Formtastic when it doesn't suit to create your own buttons, links and actions:
41
+ #
42
+ # <%= semantic_form_for @post do |f| %>
43
+ # ...
44
+ # <%= f.buttons do %>
45
+ # <li class="save">
46
+ # <%= f.submit "Save" %>
47
+ # <li>
48
+ # <li class="cancel-link">
49
+ # Or <%= link_to "Cancel", posts_url %>
50
+ # <li>
51
+ # <% end %>
52
+ # <% end %>
53
+ #
54
+ # There are many other syntax variations and arguments to customize your form. See the
55
+ # full documentation of {#buttons} and {#commit_button} for details.
56
+ module ButtonsHelper
57
+ include Formtastic::Helpers::FieldsetWrapper
58
+ include Formtastic::LocalizedString
59
+
60
+ # Creates a fieldset and ol tag wrapping for use around a set of buttons. It can be
61
+ # called either with a block (in which you can do the usual Rails form stuff, HTML, ERB, etc),
62
+ # or with a list of named buttons. These two examples are functionally equivalent:
63
+ #
64
+ # # With a block:
65
+ # <% semantic_form_for @post do |f| %>
66
+ # ...
67
+ # <% f.buttons do %>
68
+ # <%= f.commit_button %>
69
+ # <% end %>
70
+ # <% end %>
71
+ #
72
+ # # With a list of fields:
73
+ # <% semantic_form_for @post do |f| %>
74
+ # <%= f.buttons :commit %>
75
+ # <% end %>
76
+ #
77
+ # # Output:
78
+ # <form ...>
79
+ # <fieldset class="inputs">
80
+ # <ol>
81
+ # <li class="commit">
82
+ # <input type="submit" ...>
83
+ # </li>
84
+ # </ol>
85
+ # </fieldset>
86
+ # </form>
87
+ #
88
+ # Only one type of named button is supported at this time (:commit), and it's assumed to be
89
+ # the default choice, so this is also functionally equivalent, but may change in the future:
90
+ #
91
+ # # With no args:
92
+ # <% semantic_form_for @post do |f| %>
93
+ # ...
94
+ # <%= f.buttons %>
95
+ # <% end %>
96
+ #
97
+ # While this may seem slightly over-engineered, it is consistent with the way form inputs are
98
+ # handled, and makes room for other types of buttons and actions in future versions (such as
99
+ # cancel buttons or links, reset buttons and even alternate actions like 'save and continue
100
+ # editing').
101
+ #
102
+ # All options except `:name` and `:title` are passed down to the fieldset as HTML
103
+ # attributes (`id`, `class`, `style`...). If provided, the `:name` or `:title` option is
104
+ # passed into a `<legend>` inside the `<fieldset>` to name the set of buttons.
105
+ #
106
+ # @example Quickly add button(s) to the form, accepting all default values, options and behaviors
107
+ # <% semantic_form_for @post do |f| %>
108
+ # ...
109
+ # <%= f.buttons %>
110
+ # <% end %>
111
+ #
112
+ # @example Specify which named buttons you want, accepting all default values, options and behaviors
113
+ # <% semantic_form_for @post do |f| %>
114
+ # ...
115
+ # <%= f.buttons :commit %>
116
+ # <% end %>
117
+ #
118
+ # @example Specify which named buttons you want, and name the fieldset
119
+ # <% semantic_form_for @post do |f| %>
120
+ # ...
121
+ # <%= f.buttons :commit, :name => "Actions" %>
122
+ # or
123
+ # <%= f.buttons :commit, :label => "Actions" %>
124
+ # <% end %>
125
+ #
126
+ # @example Get full control over the commit_button options
127
+ # <% semantic_form_for @post do |f| %>
128
+ # ...
129
+ # <%= f.buttons do %>
130
+ # <%= f.commit_button :label => "Go", :input_html => { ... }, :wrapper_html => { ... }
131
+ # <% end %>
132
+ # <% end %>
133
+ #
134
+ # @example Make your own custom buttons, links or actions with standard Rails helpers or HTML
135
+ # <% semantic_form_for @post do |f| %>
136
+ # ...
137
+ # <%= f.buttons do %>
138
+ # <li class="submit">
139
+ # <%= f.submit "Submit" %>
140
+ # </li>
141
+ # <li class="reset">
142
+ # <input type="reset" value="Reset">
143
+ # </li>
144
+ # <li class="cancel">
145
+ # <%= link_to "Cancel", posts_url %>
146
+ # </li>
147
+ # <% end %>
148
+ # <% end %>
149
+ #
150
+ # @example Add HTML attributes to the fieldset
151
+ # <% semantic_form_for @post do |f| %>
152
+ # ...
153
+ # <%= f.buttons :commit, :style => "border:1px;" %>
154
+ # or
155
+ # <%= f.buttons :style => "border:1px;" do %>
156
+ # ...
157
+ # <% end %>
158
+ # <% end %>
159
+ #
160
+ # @option *args :label [String, Symbol]
161
+ # Optionally specify text for the legend of the fieldset
162
+ #
163
+ # @option *args :name [String, Symbol]
164
+ # Optionally specify text for the legend of the fieldset (alias for `:label`)
165
+ #
166
+ # @todo document i18n keys
167
+ def buttons(*args, &block)
168
+ html_options = args.extract_options!
169
+ html_options[:class] ||= "buttons"
170
+
171
+ if block_given?
172
+ field_set_and_list_wrapping(html_options, &block)
173
+ else
174
+ args = [:commit] if args.empty?
175
+ contents = args.map { |button_name| send(:"#{button_name}_button") }
176
+ field_set_and_list_wrapping(html_options, contents)
177
+ end
178
+ end
179
+
180
+ # Creates a submit input tag with the value "Save [model name]" (for existing records) or
181
+ # "Create [model name]" (for new records) by default. The output is an `<input>` tag with the
182
+ # `type` of `submit` and a class of either `create` or `update` (if Formtastic can determin if)
183
+ # the record is new or not) with `submit` as a fallback class. The submit button is wrapped in
184
+ # an `<li>` tag with a class of `commit`, and is intended to be rendered inside a {#buttons}
185
+ # block which wraps the button in a `fieldset` and `ol`.
186
+ #
187
+ # The textual value of the label can be changed from this default through the `:label`
188
+ # argument or through i18n.
189
+ #
190
+ # You can pass HTML attributes down to the `<input>` tag with the `:button_html` option, and
191
+ # pass HTML attributes to the wrapping `<li>` tag with the `:wrapper_html` option.
192
+ #
193
+ # @example Basic usage
194
+ # # form
195
+ # <%= semantic_form_for @post do |f| %>
196
+ # ...
197
+ # <%= f.buttons do %>
198
+ # <%= f.commit_button %>
199
+ # <% end %>
200
+ # <% end %>
201
+ #
202
+ # # output
203
+ # <form ...>
204
+ # ...
205
+ # <fieldset class="buttons">
206
+ # <input name="commit" type="submit" value="Create Post" class="create">
207
+ # </fieldset>
208
+ # </form>
209
+ #
210
+ # @example Set the value through the `:label` option
211
+ # <%= f.commit_button :label => "Go" %>
212
+ #
213
+ # @example Set the value through the optional first argument (like Rails' `f.submit`)
214
+ # <%= f.commit_button "Go" %>
215
+ #
216
+ # @example Pass HTML attributes down to the `<input>`
217
+ # <%= f.commit_button :button_html => { :class => 'pretty', :accesskey => 'g' } %>
218
+ # <%= f.commit_button :label => "Go", :button_html => { :class => 'pretty', :accesskey => 'g' } %>
219
+ # <%= f.commit_button "Go", :button_html => { :class => 'pretty', :accesskey => 'g' } %>
220
+ #
221
+ # @example Pass HTML attributes down to the `<li>` wrapper
222
+ # <%= f.commit_button :button_html => { :class => 'special', :id => 'whatever' } %>
223
+ # <%= f.commit_button :label => "Go", :button_html => { :class => 'special', :id => 'whatever' } %>
224
+ # <%= f.commit_button "Go", :button_html => { :class => 'special', :id => 'whatever' } %>
225
+ #
226
+ # @option *args :label [String, Symbol]
227
+ # Override the label text with a String or a symbold for an i18n translation key
228
+ #
229
+ # @option *args :button_html [Hash]
230
+ # Override or add to the HTML attributes to be passed down to the `<input>` tag
231
+ #
232
+ # @option *args :wrapper_html [Hash]
233
+ # Override or add to the HTML attributes to be passed down to the wrapping `<li>` tag
234
+ #
235
+ # @todo document i18n keys
236
+ # @todo strange that `:accesskey` seems to be supported in the top level args as well as `:button_html`
237
+ def commit_button(*args)
238
+ options = args.extract_options!
239
+ text = options.delete(:label) || args.shift
240
+
241
+ if @object && (@object.respond_to?(:persisted?) || @object.respond_to?(:new_record?))
242
+ key = @object.persisted? ? :update : :create
243
+
244
+ # Deal with some complications with ActiveRecord::Base.human_name and two name models (eg UserPost)
245
+ # ActiveRecord::Base.human_name falls back to ActiveRecord::Base.name.humanize ("Userpost")
246
+ # if there's no i18n, which is pretty crappy. In this circumstance we want to detect this
247
+ # fall back (human_name == name.humanize) and do our own thing name.underscore.humanize ("User Post")
248
+ if @object.class.model_name.respond_to?(:human)
249
+ object_name = @object.class.model_name.human
250
+ else
251
+ object_human_name = @object.class.human_name # default is UserPost => "Userpost", but i18n may do better ("User post")
252
+ crappy_human_name = @object.class.name.humanize # UserPost => "Userpost"
253
+ decent_human_name = @object.class.name.underscore.humanize # UserPost => "User post"
254
+ object_name = (object_human_name == crappy_human_name) ? decent_human_name : object_human_name
255
+ end
256
+ else
257
+ key = :submit
258
+ object_name = @object_name.to_s.send(label_str_method)
259
+ end
260
+
261
+ text = (localized_string(key, text, :action, :model => object_name) ||
262
+ Formtastic::I18n.t(key, :model => object_name)) unless text.is_a?(::String)
263
+
264
+ button_html = options.delete(:button_html) || {}
265
+ button_html.merge!(:class => [button_html[:class], key].compact.join(' '))
266
+
267
+ wrapper_html_class = ['commit'] # TODO: Add class reflecting on form action.
268
+ wrapper_html = options.delete(:wrapper_html) || {}
269
+ wrapper_html[:class] = (wrapper_html_class << wrapper_html[:class]).flatten.compact.join(' ')
270
+
271
+ accesskey = (options.delete(:accesskey) || default_commit_button_accesskey) unless button_html.has_key?(:accesskey)
272
+ button_html = button_html.merge(:accesskey => accesskey) if accesskey
273
+ template.content_tag(:li, Formtastic::Util.html_safe(submit(text, button_html)), wrapper_html)
274
+ end
275
+ end
276
+ end
277
+ end
@@ -0,0 +1,124 @@
1
+ module Formtastic
2
+ module Helpers
3
+ module ErrorsHelper
4
+ include Formtastic::Helpers::FileColumnDetection
5
+ include Formtastic::Helpers::Reflection
6
+ include Formtastic::LocalizedString
7
+
8
+ INLINE_ERROR_TYPES = [:sentence, :list, :first]
9
+
10
+ # Generates an unordered list of error messages on the base object and optionally for a given
11
+ # set of named attribute. This is idea for rendering a block of error messages at the top of
12
+ # the form for hidden/special/virtual attributes (the Paperclip Rails plugin does this), or
13
+ # errors on the base model.
14
+ #
15
+ # A hash can be used as the last set of arguments to pass HTML attributes to the `<ul>`
16
+ # wrapper.
17
+ #
18
+ # @example A list of errors on the base model
19
+ # <%= semantic_form_for ... %>
20
+ # <%= f.semantic_errors %>
21
+ # ...
22
+ # <% end %>
23
+ #
24
+ # @example A list of errors on the base and named attributes
25
+ # <%= semantic_form_for ... %>
26
+ # <%= f.semantic_errors :something_special %>
27
+ # ...
28
+ # <% end %>
29
+ #
30
+ # @example A list of errors on the base model, with custom HTML attributes
31
+ # <%= semantic_form_for ... %>
32
+ # <%= f.semantic_errors :class => "awesome" %>
33
+ # ...
34
+ # <% end %>
35
+ #
36
+ # @example A list of errors on the base model and named attributes, with custom HTML attributes
37
+ # <%= semantic_form_for ... %>
38
+ # <%= f.semantic_errors :something_special, :something_else, :class => "awesome", :onclick => "Awesome();" %>
39
+ # ...
40
+ # <% end %>
41
+ def semantic_errors(*args)
42
+ html_options = args.extract_options!
43
+ full_errors = args.inject([]) do |array, method|
44
+ attribute = localized_string(method, method.to_sym, :label) || humanized_attribute_name(method)
45
+ errors = Array(@object.errors[method.to_sym]).to_sentence
46
+ errors.present? ? array << [attribute, errors].join(" ") : array ||= []
47
+ end
48
+ full_errors << @object.errors[:base]
49
+ full_errors.flatten!
50
+ full_errors.compact!
51
+ return nil if full_errors.blank?
52
+ html_options[:class] ||= "errors"
53
+ template.content_tag(:ul, html_options) do
54
+ Formtastic::Util.html_safe(full_errors.map { |error| template.content_tag(:li, Formtastic::Util.html_safe(error)) }.join)
55
+ end
56
+ end
57
+
58
+ # Generates error messages for the given method, used for displaying errors right near the
59
+ # field for data entry. Uses the `:inline_errors` config to determin the right presentation,
60
+ # which may be an ordered list, a paragraph sentence containing all errors, or a paragraph
61
+ # containing just the first error. If configred to `:none`, no error is shown.
62
+ #
63
+ # See the `:inline_errors` config documentation for more details.
64
+ #
65
+ # This method is mostly used internally, but can be used in your forms when creating your own
66
+ # custom inputs, so it's been made public and aliased to `errors_on`.
67
+ #
68
+ # @example
69
+ # <%= semantic_form_for @post do |f| %>
70
+ # <li class='my-custom-text-input'>
71
+ # <%= f.label(:body) %>
72
+ # <%= f.text_field(:body) %>
73
+ # <%= f.errors_on(:body) %>
74
+ # </li>
75
+ # <% end %>
76
+ #
77
+ # @deprecated See the README for the currently supported approach to custom inputs.
78
+ def inline_errors_for(method, options = {})
79
+ ActiveSupport::Deprecation.warn('inline_errors_for and errors_on are deprecated and will be removed on or after version 2.1', caller)
80
+ if render_inline_errors?
81
+ errors = error_keys(method, options).map{|x| @object.errors[x] }.flatten.compact.uniq
82
+ send(:"error_#{inline_errors}", [*errors], options) if errors.any?
83
+ else
84
+ nil
85
+ end
86
+ end
87
+ alias :errors_on :inline_errors_for
88
+
89
+
90
+ protected
91
+
92
+ def error_keys(method, options)
93
+ @methods_for_error ||= {}
94
+ @methods_for_error[method] ||= begin
95
+ methods_for_error = [method.to_sym]
96
+ methods_for_error << file_metadata_suffixes.map{|suffix| "#{method}_#{suffix}".to_sym} if is_file?(method, options)
97
+ methods_for_error << [association_primary_key(method)] if association_macro_for_method(method) == :belongs_to
98
+ methods_for_error.flatten.compact.uniq
99
+ end
100
+ end
101
+
102
+ def has_errors?(method, options)
103
+ methods_for_error = error_keys(method,options)
104
+ @object && @object.respond_to?(:errors) && methods_for_error.any?{|error| !@object.errors[error].blank?}
105
+ end
106
+
107
+ def render_inline_errors?
108
+ @object && @object.respond_to?(:errors) && Formtastic::FormBuilder::INLINE_ERROR_TYPES.include?(inline_errors)
109
+ end
110
+
111
+ def association_macro_for_method(method) #:nodoc:
112
+ reflection = reflection_for(method)
113
+ reflection.macro if reflection
114
+ end
115
+
116
+ def association_primary_key(method)
117
+ reflection = reflection_for(method)
118
+ reflection.options[:foreign_key] if reflection && !reflection.options[:foreign_key].blank?
119
+ :"#{method}_id"
120
+ end
121
+
122
+ end
123
+ end
124
+ end