bureaucrat 0.0.3 → 0.10.0
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.
- data/README.md +120 -105
- data/Rakefile +9 -0
- data/bureaucrat.gemspec +32 -0
- data/lib/bureaucrat.rb +26 -8
- data/lib/bureaucrat/fields.rb +572 -336
- data/lib/bureaucrat/forms.rb +296 -257
- data/lib/bureaucrat/formsets.rb +235 -194
- data/lib/bureaucrat/quickfields.rb +90 -62
- data/lib/bureaucrat/temporary_uploaded_file.rb +14 -0
- data/lib/bureaucrat/utils.rb +79 -62
- data/lib/bureaucrat/validators.rb +163 -0
- data/lib/bureaucrat/widgets.rb +459 -303
- data/test/fields_test.rb +519 -380
- data/test/forms_test.rb +78 -58
- data/test/formsets_test.rb +48 -22
- data/test/test_helper.rb +20 -12
- data/test/widgets_test.rb +224 -204
- metadata +27 -36
- data/lib/bureaucrat/validation.rb +0 -130
- data/lib/bureaucrat/validation_old.rb +0 -148
- data/lib/bureaucrat/wizard.rb +0 -220
data/lib/bureaucrat/forms.rb
CHANGED
@@ -1,199 +1,284 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
module Bureaucrat
|
2
|
+
module Forms
|
3
|
+
|
4
|
+
# Instances of +BoundField+ represent a fields with associated data.
|
5
|
+
# +BoundField+s are used internally by the +Form+ class.
|
6
|
+
class BoundField
|
7
|
+
include Utils
|
8
|
+
|
9
|
+
# Field label text
|
10
|
+
attr_accessor :label, :form, :field, :name, :html_name, :html_initial_name, :help_text
|
11
|
+
|
12
|
+
# Instantiates a new +BoundField+ associated to +form+'s field +field+
|
13
|
+
# named +name+.
|
14
|
+
def initialize(form, field, name)
|
15
|
+
@form = form
|
16
|
+
@field = field
|
17
|
+
@name = name
|
18
|
+
@html_name = form.add_prefix(name)
|
19
|
+
@html_initial_name = form.add_initial_prefix(name)
|
20
|
+
@label = @field.label || pretty_name(name)
|
21
|
+
@help_text = @field.help_text || ''
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
# Renders the field.
|
25
|
+
def to_s
|
26
|
+
@field.show_hidden_initial ? as_widget + as_hidden(nil, true) : as_widget
|
27
|
+
end
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
# Errors for this field.
|
30
|
+
def errors
|
31
|
+
@form.errors.fetch(@name, @form.error_class.new)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Renders this field with the option of using alternate widgets
|
35
|
+
# and attributes.
|
36
|
+
def as_widget(widget=nil, attrs=nil, only_initial=false)
|
37
|
+
widget ||= @field.widget
|
38
|
+
attrs ||= {}
|
39
|
+
auto_id = self.auto_id
|
40
|
+
attrs[:id] ||= auto_id if auto_id && !widget.attrs.key?(:id)
|
29
41
|
|
30
|
-
|
31
|
-
widget ||= @field.widget
|
32
|
-
attrs ||= {}
|
33
|
-
auto_id = self.auto_id
|
34
|
-
attrs[:id] ||= auto_id if auto_id && !widget.attrs.key?(:id)
|
35
|
-
|
36
|
-
if !@form.bound?
|
37
|
-
data = @form.initial.fetch(@name.to_s, @field.initial)
|
38
|
-
data = data.call if data.respond_to?(:call)
|
39
|
-
else
|
40
|
-
if @field.is_a?(Fields::FileField) && @data.nil?
|
42
|
+
if !@form.bound?
|
41
43
|
data = @form.initial.fetch(@name, @field.initial)
|
44
|
+
data = data.call if data.respond_to?(:call)
|
42
45
|
else
|
43
|
-
|
46
|
+
if @field.is_a?(Fields::FileField) && @data.nil?
|
47
|
+
data = @form.initial.fetch(@name, @field.initial)
|
48
|
+
else
|
49
|
+
data = self.data
|
50
|
+
end
|
44
51
|
end
|
52
|
+
|
53
|
+
name = only_initial ? @html_initial_name : @html_name
|
54
|
+
widget.render(name.to_s, data, attrs)
|
45
55
|
end
|
46
56
|
|
47
|
-
|
57
|
+
# Renders this field as a text input.
|
58
|
+
def as_text(attrs=nil, only_initial=false)
|
59
|
+
as_widget(Widgets::TextInput.new, attrs, only_initial)
|
60
|
+
end
|
48
61
|
|
49
|
-
|
50
|
-
|
62
|
+
# Renders this field as a text area.
|
63
|
+
def as_textarea(attrs=nil, only_initial=false)
|
64
|
+
as_widget(Widgets::Textarea.new, attrs, only_initial)
|
65
|
+
end
|
51
66
|
|
52
|
-
|
53
|
-
|
54
|
-
|
67
|
+
# Renders this field as hidden.
|
68
|
+
def as_hidden(attrs=nil, only_initial=false)
|
69
|
+
as_widget(@field.hidden_widget, attrs, only_initial)
|
70
|
+
end
|
55
71
|
|
56
|
-
|
57
|
-
|
58
|
-
|
72
|
+
# The data associated to this field.
|
73
|
+
def data
|
74
|
+
@field.widget.value_from_formdata(@form.data, @html_name)
|
75
|
+
end
|
59
76
|
|
60
|
-
|
61
|
-
|
62
|
-
|
77
|
+
def value
|
78
|
+
# Returns the value for this BoundField, using the initial value if
|
79
|
+
# the form is not bound or the data otherwise.
|
63
80
|
|
64
|
-
|
65
|
-
|
66
|
-
|
81
|
+
if form.bound?
|
82
|
+
val = field.bound_data(data, form.initial.fetch(name, field.initial))
|
83
|
+
else
|
84
|
+
val = form.initial.fetch(name, field.initial)
|
85
|
+
if val.respond_to?(:call)
|
86
|
+
val = val.call
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
field.prepare_value(val)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Renders the label tag for this field.
|
94
|
+
def label_tag(contents=nil, attrs=nil)
|
95
|
+
contents ||= conditional_escape(@label)
|
96
|
+
widget = @field.widget
|
97
|
+
id_ = widget.attrs[:id] || self.auto_id
|
67
98
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
99
|
+
if id_
|
100
|
+
attrs = attrs ? flatatt(attrs) : ''
|
101
|
+
contents = "<label for=\"#{Widgets::Widget.id_for_label(id_)}\"#{attrs}>#{contents}</label>"
|
102
|
+
end
|
72
103
|
|
73
|
-
|
74
|
-
attrs = attrs ? flattatt(attrs) : ''
|
75
|
-
contents = "<label for=\"#{Widgets::Widget.id_for_label(id_)}\"#{attrs}>#{contents}</label>"
|
104
|
+
mark_safe(contents)
|
76
105
|
end
|
77
106
|
|
78
|
-
|
79
|
-
|
107
|
+
def css_classes(extra_classes = nil)
|
108
|
+
# Returns a string of space-separated CSS classes for this field.
|
80
109
|
|
81
|
-
|
82
|
-
|
83
|
-
|
110
|
+
if extra_classes.respond_to?(:split)
|
111
|
+
extra_classes = extra_classes.split
|
112
|
+
end
|
84
113
|
|
85
|
-
|
86
|
-
fauto_id = @form.auto_id
|
87
|
-
fauto_id ? fauto_id % @html_name : ''
|
88
|
-
end
|
89
|
-
end
|
114
|
+
extra_classes = Set.new(extra_classes)
|
90
115
|
|
91
|
-
|
92
|
-
|
93
|
-
|
116
|
+
if !errors.empty? && !Utils.blank_value?(form.error_css_class)
|
117
|
+
extra_classes << form.error_css_class
|
118
|
+
end
|
94
119
|
|
95
|
-
|
96
|
-
|
120
|
+
if field.required && !Utils.blank_value?(form.required_css_class)
|
121
|
+
extra_classes << form.required_css_class
|
122
|
+
end
|
97
123
|
|
98
|
-
|
99
|
-
@base_fields ||= Utils::OrderedHash.new
|
124
|
+
extra_classes.to_a.join(' ')
|
100
125
|
end
|
101
126
|
|
102
|
-
|
103
|
-
|
127
|
+
# true if the widget for this field is of the hidden kind.
|
128
|
+
def hidden?
|
129
|
+
@field.widget.hidden?
|
104
130
|
end
|
105
131
|
|
106
|
-
#
|
107
|
-
def
|
108
|
-
|
109
|
-
|
132
|
+
# Generates the id for this field.
|
133
|
+
def auto_id
|
134
|
+
fauto_id = @form.auto_id
|
135
|
+
fauto_id ? fauto_id % @html_name : ''
|
110
136
|
end
|
111
137
|
end
|
112
138
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
@files = options.fetch(:files, {})
|
122
|
-
@auto_id = options.fetch(:auto_id, 'id_%s')
|
123
|
-
@prefix = options[:prefix]
|
124
|
-
@initial = options.fetch(:initial, {})
|
125
|
-
@error_class = options.fetch(:error_class, Fields::ErrorList)
|
126
|
-
@label_suffix = options.fetch(:label_suffix, ':')
|
127
|
-
@empty_permitted = options.fetch(:empty_permitted, false)
|
128
|
-
@errors = nil
|
129
|
-
@changed_data = nil
|
130
|
-
|
131
|
-
@fields = self.class.base_fields.dup
|
132
|
-
@fields.each { |key, value| @fields[key] = value.dup }
|
133
|
-
end
|
139
|
+
# Base class for forms. Forms are a collection of fields with data that
|
140
|
+
# knows how to render and validate itself.
|
141
|
+
#
|
142
|
+
# === Bound vs Unbound forms
|
143
|
+
# A form is 'bound' if it was initialized with a set of data for its fields,
|
144
|
+
# otherwise it is 'unbound'. Only bound forms can be validated. Unbound
|
145
|
+
# forms always respond with false to +valid?+ and return an empty
|
146
|
+
# list of errors.
|
134
147
|
|
135
|
-
|
136
|
-
|
137
|
-
end
|
148
|
+
class Form
|
149
|
+
include Utils
|
138
150
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
151
|
+
# Fields associated to the form class
|
152
|
+
def self.base_fields
|
153
|
+
@base_fields ||= {}
|
154
|
+
end
|
143
155
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
156
|
+
# Declares a named field to be used on this form.
|
157
|
+
def self.field(name, field_obj)
|
158
|
+
base_fields[name] = field_obj
|
159
|
+
end
|
148
160
|
|
149
|
-
|
150
|
-
|
151
|
-
|
161
|
+
# Copy data to the child class
|
162
|
+
def self.inherited(c)
|
163
|
+
super(c)
|
164
|
+
c.instance_variable_set(:@base_fields, base_fields.dup)
|
165
|
+
end
|
152
166
|
|
153
|
-
|
154
|
-
|
155
|
-
|
167
|
+
# Error object class for this form
|
168
|
+
attr_accessor :error_class
|
169
|
+
# Required class for this form
|
170
|
+
attr_accessor :required_css_class
|
171
|
+
# Required class for this form
|
172
|
+
attr_accessor :error_css_class
|
173
|
+
# Format string for field id generator
|
174
|
+
attr_accessor :auto_id
|
175
|
+
# Hash of {field_name => initial_value}
|
176
|
+
attr_accessor :initial
|
177
|
+
# Data associated to this form {field_name => value}
|
178
|
+
attr_accessor :data
|
179
|
+
# TODO: complete implementation
|
180
|
+
attr_accessor :files
|
181
|
+
# Validated and cleaned data
|
182
|
+
attr_accessor :cleaned_data
|
183
|
+
# Fields belonging to this form
|
184
|
+
attr_accessor :fields
|
185
|
+
|
186
|
+
# Checks if this form was initialized with data.
|
187
|
+
def bound? ; @is_bound; end
|
188
|
+
|
189
|
+
# Instantiates a new form bound to the passed data (or unbound if data is nil)
|
190
|
+
#
|
191
|
+
# +data+ is a hash of {field_name => value} for this form to be bound
|
192
|
+
# (will be unbound if nil)
|
193
|
+
#
|
194
|
+
# Possible options are:
|
195
|
+
# :prefix prefix that will be used for fields when rendered
|
196
|
+
# :auto_id format string that will be used when generating
|
197
|
+
# field ids (default: 'id_%s')
|
198
|
+
# :initial hash of {field_name => default_value}
|
199
|
+
# (doesn't make a form bound)
|
200
|
+
# :error_class class used to represent errors (default: ErrorList)
|
201
|
+
# :label_suffix suffix string that will be appended to labels' text
|
202
|
+
# (default: ':')
|
203
|
+
# :empty_permitted boolean value that specifies if this form is valid
|
204
|
+
# when empty
|
205
|
+
|
206
|
+
def initialize(data=nil, options={})
|
207
|
+
@is_bound = !data.nil?
|
208
|
+
@data = StringAccessHash.new(data || {})
|
209
|
+
@files = options.fetch(:files, {})
|
210
|
+
@auto_id = options.fetch(:auto_id, 'id_%s')
|
211
|
+
@prefix = options[:prefix]
|
212
|
+
@initial = StringAccessHash.new(options.fetch(:initial, {}))
|
213
|
+
@error_class = options.fetch(:error_class, Fields::ErrorList)
|
214
|
+
@label_suffix = options.fetch(:label_suffix, ':')
|
215
|
+
@empty_permitted = options.fetch(:empty_permitted, false)
|
216
|
+
@errors = nil
|
217
|
+
@changed_data = nil
|
218
|
+
|
219
|
+
@fields = self.class.base_fields.dup
|
220
|
+
@fields.each { |key, value| @fields[key] = value.dup }
|
221
|
+
end
|
156
222
|
|
157
|
-
|
158
|
-
|
159
|
-
|
223
|
+
# Iterates over the fields
|
224
|
+
def each
|
225
|
+
@fields.each do |name, field|
|
226
|
+
yield BoundField.new(self, field, name)
|
227
|
+
end
|
228
|
+
end
|
160
229
|
|
161
|
-
|
162
|
-
|
163
|
-
|
230
|
+
# Access a named field
|
231
|
+
def [](name)
|
232
|
+
field = @fields[name] or return nil
|
233
|
+
BoundField.new(self, field, name)
|
234
|
+
end
|
164
235
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
236
|
+
# Errors for this forms (runs validations)
|
237
|
+
def errors
|
238
|
+
full_clean if @errors.nil?
|
239
|
+
@errors
|
240
|
+
end
|
170
241
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
242
|
+
# Perform validation and returns true if there are no errors
|
243
|
+
def valid?
|
244
|
+
@is_bound && (errors.nil? || errors.empty?)
|
245
|
+
end
|
175
246
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
247
|
+
# Generates a prefix for field named +field_name+
|
248
|
+
def add_prefix(field_name)
|
249
|
+
@prefix ? "#{@prefix}-#{field_name}" : field_name
|
250
|
+
end
|
180
251
|
|
181
|
-
|
182
|
-
|
183
|
-
|
252
|
+
# Generates an initial-prefix for field named +field_name+
|
253
|
+
def add_initial_prefix(field_name)
|
254
|
+
"initial-#{add_prefix(field_name)}"
|
255
|
+
end
|
256
|
+
|
257
|
+
# true if the form is valid when empty
|
258
|
+
def empty_permitted?
|
259
|
+
@empty_permitted
|
260
|
+
end
|
184
261
|
|
185
|
-
|
186
|
-
|
262
|
+
# Returns the list of errors that aren't associated to a specific field
|
263
|
+
def non_field_errors
|
264
|
+
errors.fetch(:__NON_FIELD_ERRORS, @error_class.new)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Runs all the validations for this form. If the form is invalid
|
268
|
+
# the list of errors is populated, if it is valid, cleaned_data is
|
269
|
+
# populated
|
270
|
+
def full_clean
|
271
|
+
@errors = Fields::ErrorHash.new
|
187
272
|
|
188
|
-
|
273
|
+
return unless bound?
|
189
274
|
|
190
|
-
|
275
|
+
@cleaned_data = StringAccessHash.new
|
191
276
|
|
192
|
-
|
277
|
+
return if empty_permitted? && !changed?
|
193
278
|
|
194
|
-
|
195
|
-
value = field.widget.
|
196
|
-
|
279
|
+
@fields.each do |name, field|
|
280
|
+
value = field.widget.
|
281
|
+
value_from_formdata(@data, add_prefix(name))
|
197
282
|
|
198
283
|
begin
|
199
284
|
if field.is_a?(Fields::FileField)
|
@@ -205,142 +290,96 @@ module Bureaucrat; module Forms
|
|
205
290
|
|
206
291
|
clean_method = 'clean_%s' % name
|
207
292
|
@cleaned_data[name] = send(clean_method) if respond_to?(clean_method)
|
208
|
-
rescue
|
293
|
+
rescue ValidationError => e
|
209
294
|
@errors[name] = e.messages
|
210
|
-
@cleaned_data.
|
295
|
+
@cleaned_data.delete(name)
|
211
296
|
end
|
212
297
|
end
|
213
298
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
299
|
+
begin
|
300
|
+
@cleaned_data = clean
|
301
|
+
rescue ValidationError => e
|
302
|
+
@errors[:__NON_FIELD_ERRORS] = e.messages
|
303
|
+
end
|
304
|
+
@cleaned_data = nil if @errors && !@errors.empty?
|
218
305
|
end
|
219
|
-
@cleaned_data = nil if @errors && !@errors.empty?
|
220
|
-
end
|
221
306
|
|
222
|
-
|
223
|
-
|
224
|
-
|
307
|
+
# Performs the last step of validations on the form, override in subclasses
|
308
|
+
# to customize behaviour.
|
309
|
+
def clean
|
310
|
+
@cleaned_data
|
311
|
+
end
|
225
312
|
|
226
|
-
|
227
|
-
|
228
|
-
|
313
|
+
# true if the form has data that isn't equal to its initial data
|
314
|
+
def changed?
|
315
|
+
changed_data && !changed_data.empty?
|
316
|
+
end
|
229
317
|
|
230
|
-
|
231
|
-
|
232
|
-
@changed_data
|
318
|
+
# List names for fields that have changed data
|
319
|
+
def changed_data
|
320
|
+
if @changed_data.nil?
|
321
|
+
@changed_data = []
|
233
322
|
|
234
|
-
|
323
|
+
@fields.each do |name, field|
|
235
324
|
prefixed_name = add_prefix(name)
|
236
|
-
data_value = field.widget.
|
237
|
-
|
325
|
+
data_value = field.widget.
|
326
|
+
value_from_formdata(@data, prefixed_name)
|
327
|
+
|
238
328
|
if !field.show_hidden_initial
|
239
329
|
initial_value = @initial.fetch(name, field.initial)
|
240
330
|
else
|
241
331
|
initial_prefixed_name = add_initial_prefix(name)
|
242
332
|
hidden_widget = field.hidden_widget.new
|
243
|
-
initial_value = hidden_widget.
|
244
|
-
|
333
|
+
initial_value = hidden_widget.
|
334
|
+
value_from_formdata(@data, initial_prefixed_name)
|
245
335
|
end
|
246
336
|
|
247
337
|
@changed_data << name if
|
248
338
|
field.widget.has_changed?(initial_value, data_value)
|
249
339
|
end
|
250
|
-
end
|
251
|
-
|
252
|
-
@changed_data
|
253
|
-
end
|
254
|
-
|
255
|
-
def media
|
256
|
-
@fields.values.inject(Widgets::Media.new) do |media, field|
|
257
|
-
media + field.widget.media
|
258
340
|
end
|
259
|
-
end
|
260
|
-
|
261
|
-
def multipart?
|
262
|
-
@fields.any? {|f| f.widgetneeds_multipart_form?}
|
263
|
-
end
|
264
|
-
|
265
|
-
def hidden_fields
|
266
|
-
@fields.select {|f| f.hidden?}
|
267
|
-
end
|
268
341
|
|
269
|
-
|
270
|
-
|
271
|
-
end
|
342
|
+
@changed_data
|
343
|
+
end
|
272
344
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
345
|
+
# true if this form contains fields that require the form to be
|
346
|
+
# multipart
|
347
|
+
def multipart?
|
348
|
+
@fields.any? {|f| f.widget.multipart_form?}
|
349
|
+
end
|
278
350
|
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
351
|
+
# List of hidden fields.
|
352
|
+
def hidden_fields
|
353
|
+
@fields.select {|f| f.hidden?}
|
354
|
+
end
|
283
355
|
|
284
|
-
|
285
|
-
|
356
|
+
# List of visible fields
|
357
|
+
def visible_fields
|
358
|
+
@fields.select {|f| !f.hidden?}
|
359
|
+
end
|
286
360
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
bf = BoundField.new(self, field, name)
|
292
|
-
bf_errors = @error_class.new(bf.errors.map {|e| conditional_escape(e)})
|
293
|
-
if bf.hidden?
|
294
|
-
top_errors += bf_errors.map do |e|
|
295
|
-
"(Hidden field #{name}) #{e.to_s}"
|
296
|
-
end unless bf_errors.empty?
|
297
|
-
hidden_fields << bf.to_s
|
298
|
-
else
|
299
|
-
output << error_row % bf_errors if
|
300
|
-
errors_on_separate_row && !bf_errors.empty?
|
301
|
-
|
302
|
-
label = ''
|
303
|
-
unless bf.label.nil? || bf.label.empty?
|
304
|
-
label = conditional_escape(bf.label)
|
305
|
-
label += @label_suffix if @label_suffix && label[-1,1] !~ /[:?.!]/
|
306
|
-
label = bf.label_tag(label)
|
307
|
-
end
|
361
|
+
# Attributes for labels, override in subclasses to customize behaviour
|
362
|
+
def label_attributes(name, field)
|
363
|
+
{}
|
364
|
+
end
|
308
365
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
}
|
314
|
-
output << format_string(normal_row, vars)
|
315
|
-
end
|
366
|
+
# Populates the passed object's attributes with data from the fields
|
367
|
+
def populate_object(object)
|
368
|
+
@fields.each do |name, field|
|
369
|
+
field.populate_object(object, name, @cleaned_data[name])
|
316
370
|
end
|
317
|
-
|
371
|
+
end
|
318
372
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
:errors => '', :label => '', :field => '', :help_text => ''
|
328
|
-
}
|
329
|
-
last_row = format_string(normal_row, vars)
|
330
|
-
output << last_row
|
331
|
-
end
|
332
|
-
output[-1] = last_row[0...-row_ender.length] + str_hidden + row_ender
|
333
|
-
else
|
334
|
-
output << str_hidden
|
335
|
-
end
|
373
|
+
private
|
374
|
+
|
375
|
+
# Returns the value for the field name +field_name+ from the associated
|
376
|
+
# data
|
377
|
+
def raw_value(fieldname)
|
378
|
+
field = @fields.fetch(fieldname)
|
379
|
+
prefix = add_prefix(fieldname)
|
380
|
+
field.widget.value_from_formdata(@data, prefix)
|
336
381
|
end
|
337
|
-
end
|
338
382
|
|
339
|
-
def raw_value(fieldname)
|
340
|
-
field = @fields.fetch(fieldname)
|
341
|
-
prefix = add_prefix(fieldname)
|
342
|
-
field.widget.value_from_datahash(@data, @files, prefix)
|
343
383
|
end
|
344
|
-
|
345
384
|
end
|
346
|
-
end
|
385
|
+
end
|