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,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
@@ -0,0 +1,68 @@
1
+ require 'super_form'
2
+ require 'spec_helper'
3
+
4
+ describe Field::Form do
5
+ context 'when creating a form field isolatedly' do
6
+ it 'assigns the child form to the field attribute' do
7
+ child_form = Class.new { include SuperForm }
8
+
9
+ field = Field::Form.new(:fake)
10
+ field.form_class = child_form
11
+
12
+ expect(field.attribute).to eq 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::Form.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 virtus 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
+ end
38
+
39
+ it 'returns an instance of child form as the default value' do
40
+ expect(@parent_form.child_form).to be_instance_of(@child_form)
41
+ end
42
+ end
43
+
44
+ describe '#inject validations' do
45
+ it 'forces the parent object to validate the child object' do
46
+ @parent_form.save
47
+ expect(@parent_form.errors[:base]).to eq(['Invalid child_form'])
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '#[]' do
53
+ before do
54
+ @child_form = Class.new { include SuperForm }
55
+ proxy = Field::Form[@child_form]
56
+
57
+ @field = proxy.factory(:name)
58
+ end
59
+
60
+ it 'creates a form instance' do
61
+ expect(@field).to be_instance_of(Field::Form)
62
+ end
63
+
64
+ it 'stores the child form into the form_class attribute' do
65
+ expect(@field.form_class).to eq @child_form
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,13 @@
1
+ require 'field'
2
+
3
+ describe Field::Base do
4
+ it 'responds to presenter_class' do
5
+ field = Field::Base.new(:fake)
6
+ expect(field).to respond_to :presenter_class
7
+ end
8
+
9
+ it 'presenter_class returns nil by default' do
10
+ field = Field::Base.new(:fake)
11
+ expect(field.presenter_class).to be_nil
12
+ end
13
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'person_type'
3
+
4
+ describe PersonType do
5
+ describe '#valid?' do
6
+ it "returns false when person type is invalid" do
7
+ invalid_values = %w{one two three four 3244}
8
+
9
+ invalid_values.each do |value|
10
+ person = PersonType.new(value)
11
+ expect(person).to_not be_valid
12
+ end
13
+ end
14
+
15
+ it "returns true when person type is valid" do
16
+ valid_values = [PersonType::NATURAL, PersonType::LEGAL]
17
+
18
+ valid_values.each do |value|
19
+ person = PersonType.new(value)
20
+ expect(person).to be_valid
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#value" do
26
+ context "with a valid value" do
27
+ it "returns the value" do
28
+ person = PersonType.new(PersonType::LEGAL)
29
+ expect(person.value).to eq PersonType::LEGAL
30
+ end
31
+ end
32
+
33
+ context "with an invalid value" do
34
+ it "returns nil" do
35
+ person = PersonType.new('bossal')
36
+ expect(person.value).to be_nil
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#description' do
42
+ it 'returns "Natural person" when value is "natural"' do
43
+ person = PersonType.new(PersonType::NATURAL)
44
+ expect(person.description).to eq 'Natural person'
45
+ end
46
+
47
+ it 'returns "Legal entity" when value is "legal"' do
48
+ person = PersonType.new(PersonType::LEGAL)
49
+ expect(person.description).to eq 'Legal entity'
50
+ end
51
+
52
+ it 'returns a default description otherwise' do
53
+ person = PersonType.new('bossal')
54
+ expect(person.description('Bossal')).to eq 'Bossal'
55
+ end
56
+ end
57
+
58
+ describe '.to_collection' do
59
+ it "returns an array with the collection" do
60
+ expect(PersonType.to_collection).to eq [
61
+ ['Natural person', PersonType::NATURAL],
62
+ ['Legal entity', PersonType::LEGAL],
63
+ ]
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,9 @@
1
+ require 'presenter'
2
+
3
+ describe Presenter::CNPJ do
4
+ it 'outputs a formatted CNPJ' do
5
+ presenter = Presenter::CNPJ.new('79371223118469')
6
+ cnpj = CNPJ.new('79371223118469')
7
+ expect(presenter.output).to eq(cnpj.formatted)
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'presenter'
2
+
3
+ describe Presenter::CPF do
4
+ it 'outputs a formatted CPF' do
5
+ presenter = Presenter::CPF.new('47788423165')
6
+ cpf = CPF.new('47788423165')
7
+ expect(presenter.output).to eq(cpf.formatted)
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ require 'super_form'
2
+ require 'presenter'
3
+
4
+ describe Presenter::Form do
5
+ it 'outputs each field according to its defined presenter class' do
6
+ field_class_with_presenter_class = Class.new(Field::Base) do
7
+ def presenter_class
8
+ Class.new(Presenter::Each) do
9
+ def self.__name__
10
+ 'anonymous'
11
+ end
12
+
13
+ def output
14
+ 'formatted output'
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ field_class_without_presenter_class = Class.new(Field::Base)
21
+
22
+ form_class = Class.new do
23
+ include SuperForm
24
+
25
+ add_field(field_class_with_presenter_class.new(:with_presenter))
26
+ add_field(field_class_without_presenter_class.new(:without_presenter))
27
+ end
28
+
29
+ form = form_class.new(
30
+ with_presenter: 'unformatted output',
31
+ without_presenter: 'unformattable'
32
+ )
33
+
34
+ presenter = Presenter::Form.factory(form)
35
+
36
+ expect(presenter.with_presenter).to eq('formatted output')
37
+ expect(presenter.without_presenter).to eq('unformattable')
38
+ end
39
+ end
@@ -0,0 +1,8 @@
1
+ require 'presenter'
2
+
3
+ describe Presenter::Password do
4
+ it 'outputs nil' do
5
+ presenter = Presenter::Password.new('secret')
6
+ expect(presenter.output).to eq nil
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ describe Presenter::PersonType do
2
+ it 'outputs the person type description' do
3
+ person = PersonType.new(PersonType::LEGAL)
4
+ presenter = Presenter::PersonType.new(PersonType::LEGAL)
5
+
6
+ expect(presenter.output).to eq person.description
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ require 'presenter'
2
+
3
+ describe Presenter::Telephone do
4
+ it 'outputs a formatted phone' do
5
+ presenter = Presenter::Telephone.new('8811111111')
6
+ phone = Telephone.new('8811111111')
7
+ expect(presenter.output).to eq(phone.formatted)
8
+ end
9
+ end
@@ -0,0 +1,166 @@
1
+ require 'presenter'
2
+ require File.expand_path('../../support/presenter_name', __FILE__)
3
+
4
+ module Presenter
5
+ describe Base do
6
+ it_behaves_like 'presenter nameable'
7
+
8
+ describe 'delegates to the source object' do
9
+ it 'calls the source object correspondent methods' do
10
+ source = stub_source_object([:name, :phone])
11
+ presenter = Base.new(source)
12
+
13
+ expect(source).to receive(:name)
14
+ expect(source).to receive(:phone)
15
+
16
+ presenter.name
17
+ presenter.phone
18
+ end
19
+
20
+ it 'returns the same values as the source object' do
21
+ source = stub_source_object([:name, :phone])
22
+ presenter = Base.new(source)
23
+
24
+ expect(presenter.name).to eq (source.name)
25
+ expect(presenter.phone).to eq (source.phone)
26
+ end
27
+ end
28
+
29
+ describe '.map' do
30
+ context 'with one mapping specified' do
31
+ it 'assigns specified attribute to specified "each presenter"' do
32
+ presenter = stub_presenter(:inexistent) { map :inexistent => :fake }
33
+ fake_presenter = stub_each_presenter(:fake, presenter)
34
+
35
+ expect(presenter.inexistent).to eq fake_presenter.output
36
+ end
37
+ end
38
+
39
+ context 'with multiple mappings specified' do
40
+ it 'assigns specified attributes to specified "each presenters"' do
41
+ presenter = stub_presenter(:inexistent, :power) do
42
+ map :inexistent => :fake, :power => :chord
43
+ end
44
+
45
+ fake = stub_each_presenter(:fake, presenter)
46
+ chord = stub_each_presenter(:chord, presenter)
47
+
48
+ expect(presenter.inexistent).to eq fake.output
49
+ expect(presenter.power).to eq chord.output
50
+ end
51
+ end
52
+
53
+ it 'tries to guess the presenter when no presenter is assigned' do
54
+ presenter = stub_presenter(:something) { map :something => :fake }
55
+
56
+ class Fake < Each
57
+ def output
58
+ '123456'
59
+ end
60
+ end
61
+
62
+ expect(presenter.something).to eq('123456')
63
+ end
64
+ end
65
+
66
+ describe '.use' do
67
+ context 'with one presenter specified' do
68
+ it 'uses one presenter' do
69
+ presenter = stub_presenter(:inexistent) { use :inexistent }
70
+ inexistent = stub_each_presenter(:inexistent, presenter)
71
+
72
+ expect(presenter.inexistent).to eq inexistent.output
73
+ end
74
+ end
75
+
76
+ context 'with multiple presenters specified' do
77
+ it 'uses multiple presenters' do
78
+ presenter = stub_presenter(:inexistent, :fake) do
79
+ use :inexistent, :fake
80
+ end
81
+
82
+ inexistent = stub_each_presenter(:inexistent, presenter)
83
+ fake = stub_each_presenter(:fake, presenter)
84
+
85
+ expect(presenter.inexistent).to eq inexistent.output
86
+ expect(presenter.fake).to eq fake.output
87
+ end
88
+ end
89
+
90
+ it 'tries to guess the presenter when no presenter is assigned' do
91
+ presenter = stub_presenter(:inexistent) { use :inexistent }
92
+
93
+ class Inexistent < Each
94
+ def output
95
+ '12345'
96
+ end
97
+ end
98
+
99
+ expect(presenter.inexistent).to eq('12345')
100
+ end
101
+
102
+ it 'works if given a presenter class instead of a symbol' do
103
+ each_presenter = Class.new(Each) do
104
+ def self.__name__
105
+ 'fake'
106
+ end
107
+
108
+ def output
109
+ 'it works'
110
+ end
111
+ end
112
+
113
+ presenter = stub_presenter(:fake) { map :fake => each_presenter }
114
+ expect(presenter.fake).to eq('it works')
115
+ end
116
+ end
117
+ end
118
+
119
+ describe Each do
120
+ it_behaves_like 'presenter nameable'
121
+
122
+ it 'can access the raw value' do
123
+ presenter = Each.new('some value')
124
+ expect(presenter.value).to eq('some value')
125
+ end
126
+
127
+ it 'outputs the raw value by default' do
128
+ presenter = Each.new('some value')
129
+ expect(presenter.output).to eq(presenter.value)
130
+ end
131
+
132
+ it 'delegates to :output when :to_s is called' do
133
+ presenter = Each.new('some value')
134
+ expect(presenter.to_s).to eq(presenter.output)
135
+ end
136
+ end
137
+ end
138
+
139
+ def stub_source_object(params)
140
+ source = Object.new
141
+
142
+ Array(params).each do |p|
143
+ source.stub(p).and_return(p.to_s)
144
+ end
145
+
146
+ source
147
+ end
148
+
149
+ def stub_presenter(*source_params, &block)
150
+ source = stub_source_object(source_params)
151
+ Class.new(Presenter::Base, &block).new(source)
152
+ end
153
+
154
+ def stub_each_presenter(id, presenter = nil)
155
+ each_presenter = Class.new(Presenter::Each) do
156
+ def output
157
+ 'output'
158
+ end
159
+ end.new
160
+
161
+ if presenter
162
+ presenter.send("#{id}_presenter=", each_presenter)
163
+ end
164
+
165
+ each_presenter
166
+ end