Class: Bureaucrat::Formsets::BaseFormSet

Inherits:
Object
  • Object
show all
Includes:
Bureaucrat::Fields, Bureaucrat::Forms, Utils
Defined in:
lib/bureaucrat/formsets.rb

Constant Summary

Constants included from Utils

Utils::ESCAPES

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

#blank_value?, #conditional_escape, #escape, #flatatt, #format_string, #make_bool, #make_float, #mark_safe, #pretty_name

Constructor Details

#initialize(data = nil, options = {}) ⇒ BaseFormSet

Returns a new instance of BaseFormSet.



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/bureaucrat/formsets.rb', line 51

def initialize(data=nil, options={})
  set_defaults
  @is_bound = !data.nil?
  @prefix = options.fetch(:prefix, self.class.default_prefix)
  @auto_id = options.fetch(:auto_id, 'id_%s')
  @data = data || {}
  @initial = options[:initial]
  @error_class = options.fetch(:error_class, ErrorList)
  @errors = nil
  @non_form_errors = nil

  construct_forms
end

Instance Attribute Details

#auto_idObject

Format string for field id generator



49
50
51
# File 'lib/bureaucrat/formsets.rb', line 49

def auto_id
  @auto_id
end

#can_deleteObject

Boolean that determines is this formset supports deletion



37
38
39
# File 'lib/bureaucrat/formsets.rb', line 37

def can_delete
  @can_delete
end

#can_orderObject

Boolean that determines is this formset supports reordering



35
36
37
# File 'lib/bureaucrat/formsets.rb', line 35

def can_order
  @can_order
end

#dataObject

Data associated to this formset. Hash of => value



47
48
49
# File 'lib/bureaucrat/formsets.rb', line 47

def data
  @data
end

#error_classObject

Error object class for this formset



43
44
45
# File 'lib/bureaucrat/formsets.rb', line 43

def error_class
  @error_class
end

#extraObject

Amount of extra (empty) forms on this formset



33
34
35
# File 'lib/bureaucrat/formsets.rb', line 33

def extra
  @extra
end

#formObject

Form class used for this formset forms



31
32
33
# File 'lib/bureaucrat/formsets.rb', line 31

def form
  @form
end

#formsObject

All forms in this formset



29
30
31
# File 'lib/bureaucrat/formsets.rb', line 29

def forms
  @forms
end

#initialObject

Initial data for the forms in this formset. Array of Hashes of => initial_value



45
46
47
# File 'lib/bureaucrat/formsets.rb', line 45

def initial
  @initial
end

#max_numObject

Maximum count of forms allowed on this formset



39
40
41
# File 'lib/bureaucrat/formsets.rb', line 39

def max_num
  @max_num
end

#prefixObject

Prefix that will be used when rendering form fields



41
42
43
# File 'lib/bureaucrat/formsets.rb', line 41

def prefix
  @prefix
end

Class Method Details

.default_prefixObject



24
25
26
# File 'lib/bureaucrat/formsets.rb', line 24

def self.default_prefix
  'form'
end

Instance Method Details

#[](index) ⇒ Object



69
70
71
# File 'lib/bureaucrat/formsets.rb', line 69

def [](index)
  forms[index]
end

#add_fields(form, index) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
# File 'lib/bureaucrat/formsets.rb', line 250

def add_fields(form, index)
  if can_order
    attrs = {label: 'Order', required: false}
    attrs[:initial] = index + 1 if index && index < initial_form_count
    form.fields[ORDERING_FIELD_NAME] = IntegerField.new(attrs)
  end
  if can_delete
    field = BooleanField.new(label: 'Delete', required: false)
    form.fields[DELETION_FIELD_NAME] = field
  end
end

#add_prefix(index) ⇒ Object



262
263
264
# File 'lib/bureaucrat/formsets.rb', line 262

def add_prefix(index)
  '%s-%s' % [@prefix, index]
end

#cleanObject



247
248
# File 'lib/bureaucrat/formsets.rb', line 247

def clean
end

#cleaned_dataObject

Maybe this should just go away?



153
154
155
156
157
158
# File 'lib/bureaucrat/formsets.rb', line 153

def cleaned_data
  unless valid?
    raise NoMethodError.new("'#{self.class.name}' object has no method 'cleaned_data'")
  end
  @forms.collect(&:cleaned_data)
end

#construct_form(i, options = {}) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/bureaucrat/formsets.rb', line 130

def construct_form(i, options={})
  defaults = {auto_id: @auto_id, prefix: add_prefix(i)}
  defaults[:initial] = @initial[i] if @initial && @initial[i]

  # Allow extra forms to be empty.
  defaults[:empty_permitted] = true if i >= initial_form_count
  defaults.merge!(options)
  form_data = @is_bound ? @data : nil
  form = self.form.new(form_data, defaults)
  add_fields(form, i)
  form
end

#construct_formsObject



126
127
128
# File 'lib/bureaucrat/formsets.rb', line 126

def construct_forms
  @forms = (0...total_form_count).map { |i| construct_form(i) }
end

#deleted_formsObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/bureaucrat/formsets.rb', line 160

def deleted_forms
  unless valid? && self.can_delete
    raise NoMethodError.new("'#{self.class.name}' object has no method 'deleted_forms'")
  end

  if @deleted_form_indexes.nil?
    @deleted_form_indexes = (0...total_form_count).select do |i|
      form = @forms[i]

      if i >= initial_form_count && !form.changed?
        false
      else
        should_delete_form?(form)
      end
    end
  end

  @deleted_form_indexes.map {|i| @forms[i]}
end

#each(&block) ⇒ Object



65
66
67
# File 'lib/bureaucrat/formsets.rb', line 65

def each(&block)
  forms.each(&block)
end

#errorsObject



207
208
209
210
# File 'lib/bureaucrat/formsets.rb', line 207

def errors
  full_clean if @errors.nil?
  @errors
end

#extra_formsObject



147
148
149
150
# File 'lib/bureaucrat/formsets.rb', line 147

def extra_forms
  n = initial_form_count
  @forms[n, @forms.length - n]
end

#full_cleanObject



233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/bureaucrat/formsets.rb', line 233

def full_clean
  if @is_bound
    @errors = @forms.collect(&:errors)

    begin
      self.clean
    rescue ValidationError => e
      @non_form_errors = @error_class.new(e.messages)
    end
  else
    @errors = []
  end
end

#initial_form_countObject



116
117
118
119
120
121
122
123
124
# File 'lib/bureaucrat/formsets.rb', line 116

def initial_form_count
  if @is_bound
    management_form.cleaned_data[INITIAL_FORM_COUNT]
  else
    n = @initial ? @initial.length : 0

    (self.max_num > 0 && n > self.max_num) ? self.max_num : n
  end
end

#initial_formsObject



143
144
145
# File 'lib/bureaucrat/formsets.rb', line 143

def initial_forms
  @forms[0, initial_form_count]
end

#lengthObject



73
74
75
# File 'lib/bureaucrat/formsets.rb', line 73

def length
  forms.length
end

#management_formObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/bureaucrat/formsets.rb', line 77

def management_form
  if @is_bound
    form = ManagementForm.new(@data, auto_id: @auto_id,
                              prefix: @prefix)
    unless form.valid?
      msg = 'ManagementForm data is missing or has been tampered with'
      raise ValidationError.new(msg)
    end
  else
    form = ManagementForm.new(nil, auto_id: @auto_id,
                              prefix: @prefix,
                              initial: {
                                TOTAL_FORM_COUNT => total_form_count,
                                INITIAL_FORM_COUNT => initial_form_count,
                                MAX_NUM_FORM_COUNT => self.max_num
                              })
  end
  form
end

#multipart?Boolean

Returns:

  • (Boolean)


266
267
268
# File 'lib/bureaucrat/formsets.rb', line 266

def multipart?
  @forms && @forms.first.multipart?
end

#non_form_errorsObject



203
204
205
# File 'lib/bureaucrat/formsets.rb', line 203

def non_form_errors
  @non_form_errors || @error_class.new
end

#ordered_formsObject



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/bureaucrat/formsets.rb', line 180

def ordered_forms
  unless valid? && self.can_order
    raise NoMethodError.new("'#{self.class.name}' object has no method 'ordered_forms'")
  end

  if @ordering.nil?
    @ordering = (0...total_form_count).map do |i|
      form = @forms[i]
      next if i >= initial_form_count && !form.changed?
      next if self.can_delete && should_delete_form?(form)
      [i, form.cleaned_data[ORDERING_FIELD_NAME]]
    end.compact
    @ordering.sort! do |a, b|
      if x[1].nil? then 1
      elsif y[1].nil? then -1
      else x[1] - y[1]
      end
    end
  end

  @ordering.map {|i| @forms[i.first]}
end

#should_delete_form?(form) ⇒ Boolean

Returns:

  • (Boolean)


212
213
214
215
216
# File 'lib/bureaucrat/formsets.rb', line 212

def should_delete_form?(form)
  field = form.fields[DELETION_FIELD_NAME]
  raw_value = form.send(:raw_value, DELETION_FIELD_NAME)
  field.clean(raw_value)
end

#total_form_countObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/bureaucrat/formsets.rb', line 97

def total_form_count
  if @is_bound
    management_form.cleaned_data[TOTAL_FORM_COUNT]
  else
    initial_forms = initial_form_count
    total_forms = initial_form_count + self.extra

    # Allow all existing related objects/inlines to be displayed,
    # but don't allow extra beyond max_num.
    if self.max_num > 0 && initial_forms > self.max_num
      initial_forms
    elsif self.max_num > 0 && total_forms > self.max_num
      max_num
    else
      total_forms
    end
  end
end

#valid?Boolean

Returns:

  • (Boolean)


218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/bureaucrat/formsets.rb', line 218

def valid?
  return false unless @is_bound

  forms_valid = true

  (0...total_form_count).each do |i|
    form = @forms[i]
    next if self.can_delete && should_delete_form?(form)

    forms_valid = false unless errors[i].empty?
  end

  forms_valid && non_form_errors.empty?
end