freeform 1.0.11 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Gemfile.lock +3 -3
- data/README.md +16 -17
- data/lib/freeform/form/date_params_filter.rb +34 -0
- data/lib/freeform/form/model.rb +56 -0
- data/lib/freeform/form/nested.rb +64 -39
- data/lib/freeform/form/property.rb +31 -75
- data/lib/freeform/form/validation.rb +48 -34
- data/lib/freeform/form.rb +31 -42
- data/lib/freeform/version.rb +1 -1
- data/spec/acceptance_spec.rb +140 -260
- data/spec/builder/builder_spec.rb +23 -41
- data/spec/builder/view_helper_spec.rb +7 -16
- data/spec/dummy/app/forms/project_form.rb +16 -2
- data/spec/dummy/app/models/company.rb +2 -2
- data/spec/dummy/app/models/milestone.rb +3 -3
- data/spec/dummy/app/models/project.rb +3 -3
- data/spec/dummy/app/models/task.rb +2 -2
- data/spec/dummy/db/migrate/20110710143903_initial_tables.rb +5 -5
- data/spec/dummy/db/schema.rb +6 -4
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/form/date_params_filter_spec.rb +51 -0
- data/spec/form/form_input_key_spec.rb +9 -11
- data/spec/form/model_spec.rb +244 -0
- data/spec/form/nested_spec.rb +108 -138
- data/spec/form/persistence_spec.rb +304 -0
- data/spec/form/property_spec.rb +104 -256
- data/spec/form/validation_spec.rb +114 -127
- data/spec/spec_helper.rb +6 -0
- metadata +10 -10
- data/spec/dummy/app/forms/milestone_form.rb +0 -4
- data/spec/dummy/app/forms/task_form.rb +0 -11
- data/spec/dummy/log/test.log +0 -111133
- data/spec/persistence_spec.rb +0 -645
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZmM3NmYwN2Q0MzBjODk2MTRlNzA3NjU0YWRjMWI1YTY3MjMxNjI1Yw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YjVmOTEzMDZmNTNiNmQ2MGIwZTllMGRjMmI5NWU4ODFiYWFhMzhjMw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YjU2ZDBlNTA2ZjNkZDdjZjgyMzY4NTg0NWRjZjM0ZTI0NjUwNWI5ZjZmZWMy
|
10
|
+
ZjUxNWFhZWQ2ZjZmODMyYzdmYjI4ZjJkNGIzNmEyYjhiNzNkMzMyY2E3NDMx
|
11
|
+
ZDgyOWI2M2ZlNjZiMTQxNDBkYzdjZWVmOTg0NzE3YzlhMDVlMWY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTZhNjZjYmEzZWQxOWI4YTZmMjlhMjg5MTQ4OGJiYWY1MzQyZmE3NDVlYjA0
|
14
|
+
M2I4MGM2NDhkZGRkODdiYjZjMTU0YWRhMzRhNGQ5OTEyNDU4OTZkNTI0ZDJm
|
15
|
+
OTNiMTc0ZmU1YzZhMTE2ODBiZTIxOTQ4NTk2NWY2ZTA5YjA2NGQ=
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
freeform (
|
4
|
+
freeform (2.0.0rc1)
|
5
5
|
activemodel
|
6
6
|
formtastic
|
7
7
|
rails (>= 3.2.0)
|
@@ -46,7 +46,7 @@ GEM
|
|
46
46
|
rack-test (>= 0.5.4)
|
47
47
|
selenium-webdriver (~> 2.0)
|
48
48
|
xpath (~> 0.1.4)
|
49
|
-
childprocess (0.5.
|
49
|
+
childprocess (0.5.3)
|
50
50
|
ffi (~> 1.0, >= 1.0.11)
|
51
51
|
diff-lcs (1.2.5)
|
52
52
|
erubis (2.7.0)
|
@@ -110,7 +110,7 @@ GEM
|
|
110
110
|
rspec-core (~> 2.14.0)
|
111
111
|
rspec-expectations (~> 2.14.0)
|
112
112
|
rspec-mocks (~> 2.14.0)
|
113
|
-
rubyzip (1.1.
|
113
|
+
rubyzip (1.1.3)
|
114
114
|
selenium-webdriver (2.41.0)
|
115
115
|
childprocess (>= 0.5.0)
|
116
116
|
multi_json (~> 1.0)
|
data/README.md
CHANGED
@@ -10,11 +10,13 @@ FreeForm is designed primarily with Rails in mind, but it should work on any Rub
|
|
10
10
|
|
11
11
|
**FreeForm will not work with Ryan Bate's nested_form gem, but provides its own identical behavior**
|
12
12
|
|
13
|
+
Please use/migrate to version 2.x of this gem. Version 1.x will no longer be supported, and version 2.x provides a better DSL, additional features, and cleaner source code.
|
14
|
+
|
13
15
|
## Installation
|
14
16
|
|
15
17
|
Add this line to your application's Gemfile:
|
16
18
|
|
17
|
-
gem 'freeform', '>=
|
19
|
+
gem 'freeform', '>= 2.0.0'
|
18
20
|
|
19
21
|
And then execute:
|
20
22
|
|
@@ -198,19 +200,18 @@ class UserForm < FreeForm::Form
|
|
198
200
|
property :username, :on => :user
|
199
201
|
property :email, :on => :user
|
200
202
|
|
201
|
-
has_many :phone_numbers
|
203
|
+
has_many :phone_numbers do
|
204
|
+
form_models :phone
|
205
|
+
|
206
|
+
property :area_code, :on => :phone
|
207
|
+
property :number, :on => :phone
|
208
|
+
end
|
202
209
|
|
203
210
|
def phone_initializer
|
204
211
|
{ :phone => user.phone_numbers.build }
|
205
212
|
end
|
206
213
|
end
|
207
214
|
|
208
|
-
class PhoneNumberForm < FreeForm::Form
|
209
|
-
form_models :phone
|
210
|
-
|
211
|
-
property :area_code, :on => :phone
|
212
|
-
property :number, :on => :phone
|
213
|
-
end
|
214
215
|
```
|
215
216
|
**Note:** The method `nested_form` is also aliased as `has_many` and `has_one`, if you prefer the expressiveness of that syntax. The functionality is the same in any case.
|
216
217
|
|
@@ -235,18 +236,16 @@ class UserForm < FreeForm::Form
|
|
235
236
|
property :username, :on => :user
|
236
237
|
property :email, :on => :user
|
237
238
|
|
238
|
-
has_many :phone_numbers
|
239
|
+
has_many :phone_numbers do
|
240
|
+
form_models :phone
|
239
241
|
|
240
|
-
|
241
|
-
|
242
|
+
property :area_code, :on => :phone
|
243
|
+
property :number, :on => :phone
|
242
244
|
end
|
243
|
-
end
|
244
|
-
|
245
|
-
class PhoneNumberForm < FreeForm::Form
|
246
|
-
form_models :phone
|
247
245
|
|
248
|
-
|
249
|
-
|
246
|
+
def phone_initializer
|
247
|
+
{ :phone => user.phone_numbers.build }
|
248
|
+
end
|
250
249
|
end
|
251
250
|
|
252
251
|
form = UserForm.new(:user => current_user)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module FreeForm
|
2
|
+
class DateParamsFilter
|
3
|
+
def initialize(*args)
|
4
|
+
end
|
5
|
+
|
6
|
+
def call(params)
|
7
|
+
date_attributes = {}
|
8
|
+
|
9
|
+
params.each do |attribute, value|
|
10
|
+
if value.is_a?(Hash)
|
11
|
+
call(value) # TODO: #validate should only handle local form params.
|
12
|
+
elsif matches = attribute.match(/^(\w+)\(.i\)$/)
|
13
|
+
date_attribute = matches[1]
|
14
|
+
date_attributes[date_attribute] = params_to_date(
|
15
|
+
params.delete("#{date_attribute}(1i)"),
|
16
|
+
params.delete("#{date_attribute}(2i)"),
|
17
|
+
params.delete("#{date_attribute}(3i)")
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
params.merge!(date_attributes)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def params_to_date(year, month, day)
|
26
|
+
day ||= 1 # FIXME: is that really what we want? test.
|
27
|
+
begin # TODO: test fails.
|
28
|
+
return Date.new(year.to_i, month.to_i, day.to_i)
|
29
|
+
rescue ArgumentError => e
|
30
|
+
return nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'freeform/form/date_params_filter'
|
2
|
+
|
3
|
+
module FreeForm
|
4
|
+
module Model
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
include Forwardable
|
11
|
+
|
12
|
+
def models
|
13
|
+
@models ||= []
|
14
|
+
end
|
15
|
+
|
16
|
+
def child_models
|
17
|
+
@child_models ||= []
|
18
|
+
end
|
19
|
+
|
20
|
+
def declared_models(*names)
|
21
|
+
names.each do |name|
|
22
|
+
declared_model(name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
alias_method :form_models, :declared_models
|
26
|
+
|
27
|
+
def declared_model(name, opts={})
|
28
|
+
attr_accessor name
|
29
|
+
@models = (@models || []) << name
|
30
|
+
end
|
31
|
+
alias_method :form_model, :declared_model
|
32
|
+
|
33
|
+
def child_model(name, opts={}, &block)
|
34
|
+
declared_model(name)
|
35
|
+
@child_models = (@child_models || []) << name
|
36
|
+
|
37
|
+
# Defines an initializer method, such as 'initialize_address'
|
38
|
+
# that can be called on form initialization to build the model
|
39
|
+
define_method("initialize_#{name}") do
|
40
|
+
instance_variable_set("@#{name}", instance_eval(&block))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def models
|
46
|
+
Array.new.tap do |a|
|
47
|
+
self.class.models.each do |form_model|
|
48
|
+
a << send(form_model)
|
49
|
+
end
|
50
|
+
a.flatten!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
end
|
56
|
+
end
|
data/lib/freeform/form/nested.rb
CHANGED
@@ -9,64 +9,88 @@ module FreeForm
|
|
9
9
|
#------------------------------------------------------------------------
|
10
10
|
attr_accessor :nested_forms
|
11
11
|
|
12
|
-
def nested_form(attribute, options={})
|
13
|
-
|
14
|
-
|
15
|
-
@nested_forms.merge!({:"#{attribute}" => nested_form_class})
|
12
|
+
def nested_form(attribute, options={}, &block)
|
13
|
+
# Initialize the instance variables on the parent class
|
14
|
+
initialize_instance_variables(attribute)
|
16
15
|
|
17
|
-
# Define
|
18
|
-
|
16
|
+
# Define new nested class
|
17
|
+
klass = define_nested_class(attribute, options, &block)
|
19
18
|
|
20
|
-
#
|
21
|
-
define_nested_model_methods(attribute,
|
22
|
-
|
23
|
-
# Setup Handling for nested attributes
|
24
|
-
define_nested_attribute_methods(attribute, nested_form_class)
|
19
|
+
# Define methods for working with nested models
|
20
|
+
define_nested_model_methods(attribute, klass)
|
25
21
|
end
|
26
22
|
alias_method :has_many, :nested_form
|
27
23
|
alias_method :has_one, :nested_form
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def define_nested_model_methods(attribute, form_class, options={})
|
33
|
-
singularized_attribute = attribute.to_s.singularize.to_s
|
25
|
+
protected
|
26
|
+
def initialize_instance_variables(attribute)
|
27
|
+
declared_model attribute
|
34
28
|
|
35
|
-
# Example: form.addresses will return all nested address forms
|
36
29
|
define_method(:"#{attribute}") do
|
37
30
|
value = instance_variable_get("@nested_#{attribute}")
|
38
31
|
value ||= []
|
39
32
|
instance_variable_set("@nested_#{attribute}", value)
|
40
33
|
end
|
34
|
+
end
|
41
35
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
36
|
+
def register_nested_form(klass)
|
37
|
+
@nested_forms ||= []
|
38
|
+
@nested_forms << klass
|
39
|
+
end
|
46
40
|
|
47
|
-
|
48
|
-
|
41
|
+
def parent_class
|
42
|
+
self
|
43
|
+
end
|
49
44
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
initializer ||= {}
|
45
|
+
def attribute_to_form_class(attribute)
|
46
|
+
singularized_attribute(attribute).camelize
|
47
|
+
end
|
55
48
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
value << form_model
|
61
|
-
instance_variable_set("@nested_#{attribute}", value)
|
49
|
+
def define_nested_class(attribute, options={}, &block)
|
50
|
+
# Define new nested class
|
51
|
+
klass = Class.new(FreeForm::Form) do
|
52
|
+
end
|
62
53
|
|
63
|
-
|
54
|
+
# Add whatever passed in methods, properties, etc. to the class
|
55
|
+
if block_given?
|
56
|
+
klass.class_eval(&block)
|
64
57
|
end
|
65
|
-
|
58
|
+
|
59
|
+
# Set the class name
|
60
|
+
form_class = attribute_to_form_class(attribute)
|
61
|
+
parent_class.const_set(form_class, klass)
|
62
|
+
|
63
|
+
# Register the class as being nested under the current class
|
64
|
+
register_nested_form(klass)
|
65
|
+
klass
|
66
66
|
end
|
67
67
|
|
68
|
-
|
69
|
-
|
68
|
+
def define_nested_model_methods(attribute, form_class, options={})
|
69
|
+
singular = singularized_attribute(attribute)
|
70
|
+
|
71
|
+
# Example: form.build_addresses (optional custom initializer)
|
72
|
+
define_method(:"build_#{attribute}") do |initializer=nil|
|
73
|
+
initializer ||= self.send("#{singular}_initializer")
|
74
|
+
|
75
|
+
form_class.new(initializer).tap do |obj|
|
76
|
+
# Add new object to parent model collection (e.g. the new address is in parent.addresses)
|
77
|
+
current_models = self.send(attribute)
|
78
|
+
current_models ||= []
|
79
|
+
current_models << obj
|
80
|
+
self.send("#{attribute}=", current_models)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
alias_method :"build_#{singular}", :"build_#{attribute}"
|
84
|
+
|
85
|
+
# Define methods for working with nested models
|
86
|
+
define_nested_attribute_methods(attribute, form_class)
|
87
|
+
end
|
88
|
+
|
89
|
+
def singularized_attribute(attribute)
|
90
|
+
attribute.to_s.singularize
|
91
|
+
end
|
92
|
+
|
93
|
+
#TODO: Clean up this method!
|
70
94
|
def define_nested_attribute_methods(attribute, nested_form_class)
|
71
95
|
# Equivalent of "address_attributes=" for "address" attribute
|
72
96
|
define_method(:"#{attribute}_attributes=") do |params|
|
@@ -79,12 +103,13 @@ module FreeForm
|
|
79
103
|
model.fill(attributes)
|
80
104
|
end
|
81
105
|
end
|
82
|
-
end
|
106
|
+
end
|
83
107
|
end
|
84
108
|
|
85
109
|
# Instance Methods
|
86
110
|
#--------------------------------------------------------------------------
|
87
111
|
protected
|
112
|
+
#TODO: Clean up this method!
|
88
113
|
def build_models_from_param_count(attribute, params)
|
89
114
|
# Get the difference between sets of params passed and current form objects
|
90
115
|
num_param_models = params.length
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'freeform/form/date_params_filter'
|
2
|
+
|
1
3
|
module FreeForm
|
2
4
|
module Property
|
3
5
|
def self.included(base)
|
@@ -7,43 +9,6 @@ module FreeForm
|
|
7
9
|
module ClassMethods
|
8
10
|
include Forwardable
|
9
11
|
|
10
|
-
# Models
|
11
|
-
#------------------------------------------------------------------------
|
12
|
-
def models
|
13
|
-
@models ||= []
|
14
|
-
end
|
15
|
-
|
16
|
-
def child_models
|
17
|
-
@child_models ||= []
|
18
|
-
end
|
19
|
-
|
20
|
-
def declared_model(name, opts={})
|
21
|
-
@models ||= []
|
22
|
-
@models << name
|
23
|
-
attr_accessor name
|
24
|
-
end
|
25
|
-
alias_method :form_model, :declared_model
|
26
|
-
|
27
|
-
def declared_models(*names)
|
28
|
-
names.each do |name|
|
29
|
-
declared_model(name)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
alias_method :form_models, :declared_models
|
33
|
-
|
34
|
-
def child_model(name, opts={}, &block)
|
35
|
-
@models ||= []
|
36
|
-
@models << name
|
37
|
-
@child_models ||= []
|
38
|
-
@child_models << name
|
39
|
-
attr_accessor name
|
40
|
-
define_method("initialize_#{name}") do
|
41
|
-
instance_variable_set("@#{name}", instance_eval(&block))
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Properties
|
46
|
-
#------------------------------------------------------------------------
|
47
12
|
def property_mappings
|
48
13
|
# Take the form of {:property => {:model => model, :field => field, :ignore_blank => false}}
|
49
14
|
@property_mappings ||= Hash.new
|
@@ -89,57 +54,48 @@ module FreeForm
|
|
89
54
|
end
|
90
55
|
end
|
91
56
|
|
92
|
-
attr_accessor :parent_form
|
93
|
-
|
94
|
-
class DateParamsFilter
|
95
|
-
def call(params)
|
96
|
-
date_attributes = {}
|
97
|
-
|
98
|
-
params.each do |attribute, value|
|
99
|
-
if value.is_a?(Hash)
|
100
|
-
call(value) # TODO: #validate should only handle local form params.
|
101
|
-
elsif matches = attribute.match(/^(\w+)\(.i\)$/)
|
102
|
-
date_attribute = matches[1]
|
103
|
-
date_attributes[date_attribute] = params_to_date(
|
104
|
-
params.delete("#{date_attribute}(1i)"),
|
105
|
-
params.delete("#{date_attribute}(2i)"),
|
106
|
-
params.delete("#{date_attribute}(3i)")
|
107
|
-
)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
params.merge!(date_attributes)
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
def params_to_date(year, month, day)
|
115
|
-
day ||= 1 # FIXME: is that really what we want? test.
|
116
|
-
begin # TODO: test fails.
|
117
|
-
return Date.new(year.to_i, month.to_i, day.to_i)
|
118
|
-
rescue ArgumentError => e
|
119
|
-
return nil
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
57
|
def assign_params(params)
|
125
|
-
|
126
|
-
|
127
|
-
|
58
|
+
self.tap do |s|
|
59
|
+
FreeForm::DateParamsFilter.new.call(params)
|
60
|
+
before_assign_params(params)
|
61
|
+
params.each_pair do |attribute, value|
|
62
|
+
assign_attribute(attribute, value)
|
63
|
+
end
|
64
|
+
after_assign_params(params)
|
128
65
|
end
|
129
|
-
self
|
130
66
|
end
|
131
67
|
alias_method :assign_attributes, :assign_params
|
132
68
|
alias_method :populate, :assign_params
|
133
69
|
alias_method :fill, :assign_params
|
134
70
|
|
71
|
+
def before_assign_params(params)
|
72
|
+
end
|
73
|
+
alias_method :before_assign_attributes, :before_assign_params
|
74
|
+
alias_method :before_populate, :before_assign_params
|
75
|
+
alias_method :before_fill, :before_assign_params
|
76
|
+
|
77
|
+
def after_assign_params(params)
|
78
|
+
end
|
79
|
+
alias_method :after_assign_attributes, :after_assign_params
|
80
|
+
alias_method :after_populate, :after_assign_params
|
81
|
+
alias_method :after_fill, :after_assign_params
|
82
|
+
|
83
|
+
def model_property_mappings
|
84
|
+
self.class.property_mappings
|
85
|
+
end
|
86
|
+
|
135
87
|
private
|
136
88
|
def assign_attribute(attribute, value)
|
137
89
|
self.send :"#{attribute}=", value unless ignore?(attribute, value)
|
138
90
|
end
|
139
91
|
|
140
92
|
def ignore?(attribute, value)
|
141
|
-
mapping =
|
142
|
-
|
93
|
+
mapping = model_property_mappings[attribute.to_sym]
|
94
|
+
if mapping.present?
|
95
|
+
mapping[:ignore_blank] && value.blank?
|
96
|
+
else
|
97
|
+
false
|
98
|
+
end
|
143
99
|
end
|
144
100
|
end
|
145
101
|
end
|
@@ -6,59 +6,73 @@ module FreeForm
|
|
6
6
|
end
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
+
def validate_nested_forms
|
10
|
+
validate :validate_nested_forms
|
11
|
+
end
|
12
|
+
|
9
13
|
def validate_models
|
10
|
-
validate :
|
14
|
+
validate :validate_component_models
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
14
18
|
protected
|
15
|
-
def
|
16
|
-
|
17
|
-
if send(form_model).is_a?(Array)
|
18
|
-
# If it's an array, we're dealing with nested forms
|
19
|
-
errors.add(:base, "has invalid nested forms") unless validate_nested_forms(send(form_model))
|
20
|
-
else
|
21
|
-
# Otherwise, validate the form object
|
22
|
-
validate_form_model(form_model)
|
23
|
-
end
|
24
|
-
end
|
19
|
+
def validate_nested_forms
|
20
|
+
models.each { |m| validate_nested_form(m) if m.is_a?(FreeForm::Form) }
|
25
21
|
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
form_validity = true
|
30
|
-
form_array.each do |model|
|
31
|
-
destroyed = model.respond_to?(:marked_for_destruction?) ? model.marked_for_destruction? : false
|
32
|
-
unless model.valid? || destroyed
|
33
|
-
form_validity = false
|
34
|
-
end
|
35
|
-
end
|
36
|
-
form_validity
|
23
|
+
def validate_component_models
|
24
|
+
models.each { |m| validate_model(m) unless m.is_a?(FreeForm::Form) }
|
37
25
|
end
|
38
26
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
return model.valid?
|
27
|
+
private
|
28
|
+
def validate_nested_form(form)
|
29
|
+
errors.add(:base, "has invalid nested forms") unless marked_for_destruction_or_valid?(form)
|
43
30
|
end
|
44
31
|
|
45
|
-
def
|
46
|
-
model = send(form_model)
|
32
|
+
def validate_model(model)
|
47
33
|
model.valid?
|
34
|
+
add_model_errors_to_form(model)
|
35
|
+
end
|
36
|
+
|
37
|
+
def marked_for_destruction_or_valid?(form)
|
38
|
+
form_marked_for_destruction?(form) || form.valid?
|
39
|
+
end
|
40
|
+
|
41
|
+
def form_marked_for_destruction?(form)
|
42
|
+
form.respond_to?(:marked_for_destruction?) ? form.marked_for_destruction? : false
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_model_errors_to_form(model)
|
48
46
|
model.errors.each do |error, message|
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
add_error_to_form(model, error, message)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_error_to_form(model, error, message)
|
52
|
+
field = find_form_field_from_model_field(model, error)
|
53
|
+
if field
|
54
|
+
errors.add(field, message)
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
55
|
-
def find_form_field_from_model_field(model,
|
56
|
-
|
57
|
-
|
58
|
+
def find_form_field_from_model_field(model, error_field)
|
59
|
+
model_property_mappings.each_pair do |property, attributes|
|
60
|
+
model_sym = model_symbol_from_model(model)
|
61
|
+
field_sym = error_field.to_sym
|
62
|
+
|
63
|
+
if (attributes[:model] == model_sym) && (attributes[:field] == field_sym)
|
58
64
|
return property
|
59
65
|
end
|
60
66
|
end
|
61
|
-
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def model_symbol_from_model(model)
|
71
|
+
models_as_symbols.find { |sym| return sym if send(sym) == model }
|
72
|
+
end
|
73
|
+
|
74
|
+
def models_as_symbols
|
75
|
+
self.class.models.map { |x| x.to_sym }
|
62
76
|
end
|
63
77
|
end
|
64
78
|
end
|