nuatt-formtastic 0.2.2 → 0.2.3

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 (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