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.
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