super_form 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/lib/field.rb +15 -9
- data/lib/field/bare.rb +3 -0
- data/lib/field/base.rb +54 -15
- data/lib/field/cnpj.rb +5 -7
- data/lib/field/cpf.rb +6 -8
- data/lib/field/email.rb +4 -4
- data/lib/field/float.rb +7 -0
- data/lib/field/form.rb +30 -0
- data/lib/field/form_array.rb +32 -0
- data/lib/field/form_proxy.rb +16 -0
- data/lib/field/password.rb +6 -10
- data/lib/field/person_type.rb +0 -4
- data/lib/field/telephone.rb +2 -7
- data/lib/person_type.rb +2 -8
- data/lib/presenter.rb +90 -0
- data/lib/presenter/cnpj.rb +9 -0
- data/lib/presenter/cpf.rb +9 -0
- data/lib/presenter/form.rb +20 -0
- data/lib/presenter/password.rb +7 -0
- data/lib/presenter/person_type.rb +9 -0
- data/lib/presenter/telephone.rb +9 -0
- data/lib/super_form.rb +21 -156
- data/lib/super_form/fieldable.rb +78 -0
- data/lib/super_form/fieldset.rb +32 -0
- data/lib/super_form/version.rb +1 -1
- data/spec/lib/field/form_array.rb +71 -0
- data/spec/lib/field/form_array_spec.rb +71 -0
- data/spec/lib/field/form_spec.rb +68 -0
- data/spec/lib/field_spec.rb +13 -0
- data/spec/lib/person_type_spec.rb +66 -0
- data/spec/lib/presenter/cnpj_spec.rb +9 -0
- data/spec/lib/presenter/cpf_spec.rb +9 -0
- data/spec/lib/presenter/form_spec.rb +39 -0
- data/spec/lib/presenter/password_spec.rb +8 -0
- data/spec/lib/presenter/person_type_spec.rb +8 -0
- data/spec/lib/presenter/telephone_spec.rb +9 -0
- data/spec/lib/presenter_spec.rb +166 -0
- data/spec/lib/super_form/fieldable_spec.rb +82 -0
- data/spec/lib/super_form_spec.rb +120 -65
- data/spec/lib/telephone_spec.rb +32 -0
- data/spec/spec_helper.rb +4 -11
- data/spec/support/presenter_name.rb +28 -0
- data/super_form.gemspec +1 -0
- metadata +60 -2
@@ -0,0 +1,20 @@
|
|
1
|
+
module Presenter
|
2
|
+
class Form < Base
|
3
|
+
def self.factory(form)
|
4
|
+
presenters = form.fields.each_with_object({}) do |field, p|
|
5
|
+
name, field = field
|
6
|
+
p[name] = field.presenter_class if field.presenter_class
|
7
|
+
end
|
8
|
+
|
9
|
+
presenter_class = Class.new(Base) do
|
10
|
+
map presenters
|
11
|
+
|
12
|
+
def self.__name__
|
13
|
+
'form'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
presenter_class.new(form)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/super_form.rb
CHANGED
@@ -1,39 +1,23 @@
|
|
1
|
-
require "super_form/version"
|
2
|
-
|
3
|
-
require 'field'
|
4
|
-
require 'attribute'
|
5
|
-
require 'virtus'
|
6
|
-
require 'active_support/inflector'
|
7
1
|
require 'active_support/concern'
|
8
|
-
require '
|
2
|
+
require 'virtus'
|
3
|
+
require 'super_form/fieldable'
|
4
|
+
require "super_form/version"
|
9
5
|
|
10
6
|
autoload :UniquenessValidator, 'uniqueness_validator'
|
11
7
|
|
12
8
|
module SuperForm
|
13
|
-
|
14
|
-
|
15
|
-
Virtus.model(@virtus_options)
|
16
|
-
else
|
17
|
-
Virtus.model
|
18
|
-
end
|
19
|
-
|
20
|
-
klass.include virtus
|
21
|
-
klass.include ActiveModel::Conversion
|
22
|
-
klass.include ActiveModel::Validations
|
23
|
-
klass.extend ActiveModel::Naming
|
24
|
-
klass.extend ActiveModel::Callbacks
|
25
|
-
klass.extend ClassMethods
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
include Fieldable
|
26
11
|
|
27
|
-
|
28
|
-
|
12
|
+
included do
|
13
|
+
include Virtus.model
|
29
14
|
|
30
|
-
|
31
|
-
|
32
|
-
@virtus_options = nil
|
15
|
+
class_eval &SuperForm.callbacks
|
16
|
+
class_eval &SuperForm.constructor
|
33
17
|
end
|
34
18
|
|
35
|
-
def self.
|
36
|
-
|
19
|
+
def self.constructor
|
20
|
+
Proc.new do
|
37
21
|
alias_method :original_initializer, :initialize
|
38
22
|
|
39
23
|
def initialize(*args)
|
@@ -43,8 +27,8 @@ module SuperForm
|
|
43
27
|
end
|
44
28
|
end
|
45
29
|
|
46
|
-
def self.
|
47
|
-
|
30
|
+
def self.callbacks
|
31
|
+
Proc.new do
|
48
32
|
alias_method :ar_valid?, :valid?
|
49
33
|
|
50
34
|
def valid?
|
@@ -57,40 +41,16 @@ module SuperForm
|
|
57
41
|
end
|
58
42
|
end
|
59
43
|
|
60
|
-
def self.base(virtus_options = {})
|
61
|
-
@virtus_options = virtus_options
|
62
|
-
Form
|
63
|
-
end
|
64
|
-
|
65
44
|
def setup
|
66
|
-
|
67
|
-
|
45
|
+
if self.class.setup
|
46
|
+
instance_eval(&self.class.setup)
|
47
|
+
end
|
68
48
|
end
|
69
49
|
|
70
50
|
def persisted?
|
71
51
|
false
|
72
52
|
end
|
73
53
|
|
74
|
-
def fields
|
75
|
-
@fields
|
76
|
-
end
|
77
|
-
|
78
|
-
def field(name)
|
79
|
-
if self.class.form?(name)
|
80
|
-
send(name)
|
81
|
-
else
|
82
|
-
@fields.fetch(name)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def form?
|
87
|
-
true
|
88
|
-
end
|
89
|
-
|
90
|
-
def form_label
|
91
|
-
self.class.name.to_s.gsub(/Form$/, '').humanize
|
92
|
-
end
|
93
|
-
|
94
54
|
def save
|
95
55
|
if valid?
|
96
56
|
run_callbacks :save do
|
@@ -102,25 +62,9 @@ module SuperForm
|
|
102
62
|
end
|
103
63
|
end
|
104
64
|
|
105
|
-
|
106
|
-
|
107
|
-
def initialize_fields
|
108
|
-
@fields = {}
|
109
|
-
@fieldsets = {}
|
65
|
+
def persist!; end
|
110
66
|
|
111
|
-
|
112
|
-
self.class.fields.each do |id, field|
|
113
|
-
if self.class.form?(id)
|
114
|
-
@fields[id] = field
|
115
|
-
|
116
|
-
fieldset = self.class.child_form_fieldsets[id]
|
117
|
-
(@fieldsets[fieldset] ||= []) << @fields[id]
|
118
|
-
else
|
119
|
-
@fields[id] = field.dup
|
120
|
-
(@fieldsets[field.fieldset] ||= []) << @fields[id]
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
67
|
+
private
|
124
68
|
|
125
69
|
module ClassMethods
|
126
70
|
def setup(&block)
|
@@ -128,88 +72,9 @@ module SuperForm
|
|
128
72
|
@setup
|
129
73
|
end
|
130
74
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
# fieldset may be extracted as a domain object
|
136
|
-
def fieldset(id)
|
137
|
-
initialize_fieldset(id)
|
138
|
-
yield
|
139
|
-
close_fieldset
|
140
|
-
end
|
141
|
-
|
142
|
-
def child_form_fieldsets
|
143
|
-
@child_form_fieldsets ||= {}
|
144
|
-
end
|
145
|
-
|
146
|
-
# take care of branches here
|
147
|
-
def field(name, field_class, options = {})
|
148
|
-
if field_class.ancestors.include? SuperForm
|
149
|
-
child_form_fieldsets[name] = current_fieldset_name
|
150
|
-
attribute name, field_class
|
151
|
-
|
152
|
-
define_method(name) do
|
153
|
-
var = :"@#{name.to_s}"
|
154
|
-
value = instance_variable_get(var)
|
155
|
-
|
156
|
-
unless value
|
157
|
-
value = instance_variable_set(var, field_class.new)
|
158
|
-
end
|
159
|
-
|
160
|
-
value
|
161
|
-
end
|
162
|
-
|
163
|
-
create_child_validation(name)
|
164
|
-
field = name
|
165
|
-
else
|
166
|
-
field = field_class.new(name, current_fieldset_name)
|
167
|
-
|
168
|
-
field.add_validations(self, options)
|
169
|
-
field.add_attributes(self, options)
|
170
|
-
|
171
|
-
alias_method :"original_#{name.to_s}=", "#{name}="
|
172
|
-
|
173
|
-
define_method "#{name}=" do |value|
|
174
|
-
field = self.field(name)
|
175
|
-
field.value = value if field
|
176
|
-
|
177
|
-
send "original_#{name.to_s}=", value
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
fields[name] = field
|
182
|
-
end
|
183
|
-
|
184
|
-
def fields
|
185
|
-
@fields ||= {}
|
186
|
-
end
|
187
|
-
|
188
|
-
private
|
189
|
-
|
190
|
-
def initialize_fieldset(id)
|
191
|
-
@current = id
|
192
|
-
end
|
193
|
-
|
194
|
-
def close_fieldset
|
195
|
-
@current = nil
|
196
|
-
end
|
197
|
-
|
198
|
-
def current_fieldset_name
|
199
|
-
@current ||= default_fieldset_name
|
200
|
-
end
|
201
|
-
|
202
|
-
def default_fieldset_name
|
203
|
-
:general
|
204
|
-
end
|
205
|
-
|
206
|
-
def create_child_validation(name)
|
207
|
-
validate :"ensure_valid_#{name.to_s}"
|
208
|
-
|
209
|
-
define_method "ensure_valid_#{name.to_s}" do
|
210
|
-
unless send(name).send(:valid?)
|
211
|
-
errors.add(:base, "Invalid #{name.to_s}")
|
212
|
-
end
|
75
|
+
def model_name
|
76
|
+
if name = self.name || self.to_s
|
77
|
+
ActiveModel::Name.new(self, nil, name.gsub(/Form$/, ''))
|
213
78
|
end
|
214
79
|
end
|
215
80
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_model'
|
3
|
+
require 'field'
|
4
|
+
|
5
|
+
module SuperForm
|
6
|
+
module Fieldable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include ActiveModel::Model
|
9
|
+
|
10
|
+
def fields
|
11
|
+
@fields ||= self.class.fields.each_with_object({}) do |field, f|
|
12
|
+
f[field.name] = field.dup
|
13
|
+
f[field.name].form = self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def field(name)
|
18
|
+
fields.fetch(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def fieldsets
|
22
|
+
@fieldsets ||= self.class.fieldsets.each_with_object({}) do |fieldset, f|
|
23
|
+
id, fields = fieldset
|
24
|
+
|
25
|
+
fields.each_with_object(f) do |field|
|
26
|
+
(f[id] ||= Fieldset.new(id)) << self.field(field)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def fieldset(id)
|
32
|
+
fieldsets.fetch(id)
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
def field(field_id, field_class, options = {})
|
37
|
+
field = field_class.factory(field_id, options)
|
38
|
+
add_field(field)
|
39
|
+
end
|
40
|
+
|
41
|
+
def fields
|
42
|
+
@fields ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
def fieldset(id)
|
46
|
+
open_fieldset(id)
|
47
|
+
yield
|
48
|
+
close_fieldset
|
49
|
+
end
|
50
|
+
|
51
|
+
def fieldsets
|
52
|
+
@fieldsets ||= {}
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def add_field(field)
|
58
|
+
field.setup_container(self)
|
59
|
+
|
60
|
+
fields << field
|
61
|
+
current_fieldset << field.name
|
62
|
+
end
|
63
|
+
|
64
|
+
def open_fieldset(id)
|
65
|
+
@current = id
|
66
|
+
fieldsets[@current] ||= []
|
67
|
+
end
|
68
|
+
|
69
|
+
def close_fieldset
|
70
|
+
@current = nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def current_fieldset
|
74
|
+
fieldsets[@current] || open_fieldset(:default)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module SuperForm
|
2
|
+
class Fieldset
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :id, :fields
|
6
|
+
|
7
|
+
def initialize(id)
|
8
|
+
@id = id
|
9
|
+
@fields = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_field(field)
|
13
|
+
@fields[field.name] = field
|
14
|
+
end
|
15
|
+
|
16
|
+
def <<(field)
|
17
|
+
add_field(field)
|
18
|
+
end
|
19
|
+
|
20
|
+
def field(field_id)
|
21
|
+
@fields[field_id]
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](field_id)
|
25
|
+
field(field_id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def each(&block)
|
29
|
+
@fields.each { |field_id| block.call(field_id) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/super_form/version.rb
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'super_form'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Field::FormArray do
|
5
|
+
context 'when creating a form collection field' do
|
6
|
+
it 'assigns an array of child forms to the field attribute' do
|
7
|
+
child_form = Class.new { include SuperForm }
|
8
|
+
|
9
|
+
field = Field::FormArray.new(:fake)
|
10
|
+
field.form_class = child_form
|
11
|
+
|
12
|
+
expect(field.attribute).to eq Array[child_form]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when the form field has a container' do
|
17
|
+
before do
|
18
|
+
@child_form = Class.new do
|
19
|
+
include SuperForm
|
20
|
+
|
21
|
+
field :name, Field::Text, presence: true
|
22
|
+
end
|
23
|
+
|
24
|
+
parent_form = Class.new { include SuperForm }
|
25
|
+
|
26
|
+
field = Field::FormArray.new(:child_form)
|
27
|
+
field.form_class = @child_form
|
28
|
+
field.setup_container(parent_form)
|
29
|
+
|
30
|
+
@parent_form = parent_form.new
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#inject_attributes' do
|
34
|
+
it 'injects attributes into the parent form' do
|
35
|
+
expect(@parent_form).to respond_to :child_form=
|
36
|
+
expect(@parent_form).to respond_to :child_form
|
37
|
+
expect(@parent_form.child_form).to eq []
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#inject validations' do
|
42
|
+
it 'forces the parent object to validate the child object' do
|
43
|
+
@parent_form.child_form = [@child_form.new, @child_form.new, @child_form.new]
|
44
|
+
@parent_form.save
|
45
|
+
errors = [
|
46
|
+
'Invalid child_form on row 1',
|
47
|
+
'Invalid child_form on row 2',
|
48
|
+
'Invalid child_form on row 3'
|
49
|
+
]
|
50
|
+
expect(@parent_form.errors[:base]).to eq(errors)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#[]' do
|
56
|
+
before do
|
57
|
+
@child_form = Class.new { include SuperForm }
|
58
|
+
proxy = Field::FormArray[@child_form]
|
59
|
+
|
60
|
+
@field = proxy.factory(:name)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'creates a form instance' do
|
64
|
+
expect(@field).to be_instance_of(Field::FormArray)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'stores the child form into the form_class attribute' do
|
68
|
+
expect(@field.form_class).to eq @child_form
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|