super_form 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/field.rb +15 -9
  3. data/lib/field/bare.rb +3 -0
  4. data/lib/field/base.rb +54 -15
  5. data/lib/field/cnpj.rb +5 -7
  6. data/lib/field/cpf.rb +6 -8
  7. data/lib/field/email.rb +4 -4
  8. data/lib/field/float.rb +7 -0
  9. data/lib/field/form.rb +30 -0
  10. data/lib/field/form_array.rb +32 -0
  11. data/lib/field/form_proxy.rb +16 -0
  12. data/lib/field/password.rb +6 -10
  13. data/lib/field/person_type.rb +0 -4
  14. data/lib/field/telephone.rb +2 -7
  15. data/lib/person_type.rb +2 -8
  16. data/lib/presenter.rb +90 -0
  17. data/lib/presenter/cnpj.rb +9 -0
  18. data/lib/presenter/cpf.rb +9 -0
  19. data/lib/presenter/form.rb +20 -0
  20. data/lib/presenter/password.rb +7 -0
  21. data/lib/presenter/person_type.rb +9 -0
  22. data/lib/presenter/telephone.rb +9 -0
  23. data/lib/super_form.rb +21 -156
  24. data/lib/super_form/fieldable.rb +78 -0
  25. data/lib/super_form/fieldset.rb +32 -0
  26. data/lib/super_form/version.rb +1 -1
  27. data/spec/lib/field/form_array.rb +71 -0
  28. data/spec/lib/field/form_array_spec.rb +71 -0
  29. data/spec/lib/field/form_spec.rb +68 -0
  30. data/spec/lib/field_spec.rb +13 -0
  31. data/spec/lib/person_type_spec.rb +66 -0
  32. data/spec/lib/presenter/cnpj_spec.rb +9 -0
  33. data/spec/lib/presenter/cpf_spec.rb +9 -0
  34. data/spec/lib/presenter/form_spec.rb +39 -0
  35. data/spec/lib/presenter/password_spec.rb +8 -0
  36. data/spec/lib/presenter/person_type_spec.rb +8 -0
  37. data/spec/lib/presenter/telephone_spec.rb +9 -0
  38. data/spec/lib/presenter_spec.rb +166 -0
  39. data/spec/lib/super_form/fieldable_spec.rb +82 -0
  40. data/spec/lib/super_form_spec.rb +120 -65
  41. data/spec/lib/telephone_spec.rb +32 -0
  42. data/spec/spec_helper.rb +4 -11
  43. data/spec/support/presenter_name.rb +28 -0
  44. data/super_form.gemspec +1 -0
  45. metadata +60 -2
@@ -0,0 +1,9 @@
1
+ require 'cnpj'
2
+
3
+ module Presenter
4
+ class CNPJ < Each
5
+ def output
6
+ ::CNPJ.new(value).formatted
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'cpf'
2
+
3
+ module Presenter
4
+ class CPF < Each
5
+ def output
6
+ ::CPF.new(value).formatted
7
+ end
8
+ end
9
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ module Presenter
2
+ class Password < Each
3
+ def output
4
+ nil
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require 'person_type'
2
+
3
+ module Presenter
4
+ class PersonType < Each
5
+ def output
6
+ ::PersonType.new(value).description
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'telephone'
2
+
3
+ module Presenter
4
+ class Telephone < Each
5
+ def output
6
+ ::Telephone.new(value).formatted
7
+ end
8
+ end
9
+ 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 'active_model'
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
- def self.included(klass)
14
- virtus = if @virtus_options
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
- add_callbacks(klass)
28
- add_constructor(klass)
12
+ included do
13
+ include Virtus.model
29
14
 
30
- klass.send(:attr_reader, :fieldsets)
31
-
32
- @virtus_options = nil
15
+ class_eval &SuperForm.callbacks
16
+ class_eval &SuperForm.constructor
33
17
  end
34
18
 
35
- def self.add_constructor(klass)
36
- klass.class_eval do
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.add_callbacks(klass)
47
- klass.class_eval do
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
- initialize_fields
67
- instance_eval(&self.class.setup) if self.class.setup
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
- private
106
-
107
- def initialize_fields
108
- @fields = {}
109
- @fieldsets = {}
65
+ def persist!; end
110
66
 
111
- # take care of branches here
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 form?(field_id = nil)
132
- field_id.nil? ? true : child_form_fieldsets.has_key?(field_id)
133
- end
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
@@ -1,3 +1,3 @@
1
1
  module SuperForm
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -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