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,82 @@
1
+ require 'spec_helper'
2
+ require 'super_form/fieldable'
3
+ require 'field/bare'
4
+
5
+ describe SuperForm::Fieldable do
6
+ context 'when no fieldset is defined' do
7
+ it 'returns no fieldsets' do
8
+ expect(class_with_no_fields.fieldsets).to eq({})
9
+ end
10
+ end
11
+
12
+ context 'when fields and fieldsets are defined' do
13
+ let(:dummy) { class_with_fields }
14
+
15
+ it 'has the right number of fields' do
16
+ expect(dummy.fields.length).to eq 5
17
+ end
18
+
19
+ it 'has field values which are the same as the form attributes' do
20
+ dummy.name = 'Thiago'
21
+ dummy.ball = "Let's have it"
22
+ dummy.car = "Let's drive it"
23
+ dummy.email = "findme@athome.com"
24
+ dummy.phone = '12345'
25
+
26
+ expect(dummy.field(:name).value).to eq dummy.name
27
+ expect(dummy.field(:ball).value).to eq dummy.ball
28
+ expect(dummy.field(:car).value).to eq dummy.car
29
+ expect(dummy.field(:email).value).to eq dummy.email
30
+ expect(dummy.field(:phone).value).to eq dummy.phone
31
+ end
32
+
33
+ it 'defines fieldsets which contain form fields' do
34
+ general = dummy.fieldset(:general)
35
+ expect(general.fields).to eq({
36
+ name: dummy.field(:name)
37
+ })
38
+
39
+ toys = dummy.fieldset(:toys)
40
+ expect(toys.fields).to eq ({
41
+ ball: dummy.field(:ball),
42
+ car: dummy.field(:car)
43
+ })
44
+ end
45
+
46
+ it 'uses :default fieldset for fields defined outside a fieldset' do
47
+ default = dummy.fieldset(:default)
48
+ expect(default.fields).to eq ({
49
+ email: dummy.field(:email),
50
+ phone: dummy.field(:phone)
51
+ })
52
+ end
53
+ end
54
+ end
55
+
56
+ def class_with_fields(&block)
57
+ Class.new do
58
+ include SuperForm::Fieldable
59
+
60
+ attr_accessor :name, :ball, :car, :email, :phone
61
+
62
+ fieldset :general do
63
+ field :name, Field::Text, presence: true
64
+ end
65
+
66
+ fieldset :toys do
67
+ field :ball, Field::Bare
68
+ field :car, Field::Text
69
+ end
70
+
71
+ field :email, Field::Text
72
+ field :phone, Field::Text, length: { minimum: 4 }
73
+
74
+ instance_eval(&block) if block_given?
75
+ end.new
76
+ end
77
+
78
+ def class_with_no_fields
79
+ Class.new do
80
+ include SuperForm::Fieldable
81
+ end
82
+ end
@@ -1,98 +1,153 @@
1
- require 'spec_helper'
2
1
  require 'super_form'
3
- require 'active_model'
2
+ require 'field/bare'
3
+ require 'spec_helper'
4
4
 
5
- module Field
6
- class Null < Base; end
7
- end
5
+ describe SuperForm do
6
+ it 'includes the Fieldable module' do
7
+ form = Class.new { include SuperForm }
8
+ expect(form.ancestors).to include SuperForm::Fieldable
9
+ end
8
10
 
9
- class DummyForm
10
- include SuperForm
11
- end
11
+ it 'runs the setup method when instantiated' do
12
+ form = Class.new do
13
+ include SuperForm
14
+ attr_reader :test_setup
12
15
 
13
- describe SuperForm do
14
- before(:all) do
15
- DummyForm.class_eval do
16
- fieldset :general do
17
- field :name, Field::Text, presence: true
16
+ setup { @test_setup = 'it worked' }
17
+ end
18
+
19
+ expect(form.new.test_setup).to eq('it worked')
20
+ end
21
+
22
+ it 'is never persisted' do
23
+ form = form_with_fields
24
+ form.name = 'Thiago'
25
+ form.save
26
+
27
+ expect(form.persisted?).to be_false
28
+ expect(form_with_no_fields.persisted?).to be_false
29
+ end
30
+
31
+ describe 'ActiveModel naming' do
32
+ context 'when the class name method returns nil' do
33
+ it 'relies on to_s to guess the model name' do
34
+ form = Class.new { include SuperForm }
35
+
36
+ expect(form).to receive(:name)
37
+ expect(form).to receive(:to_s)
38
+
39
+ form.model_name
18
40
  end
19
41
 
20
- fieldset :toys do
21
- field :ball, Field::Null
22
- field :car, Field::Text
42
+ it 'returns the correct model name' do
43
+ form = Class.new { include SuperForm }
44
+ form.stub(:to_s).and_return('InexistentForm')
45
+
46
+ expect(form.model_name.name).to eq 'Inexistent'
23
47
  end
24
48
  end
25
49
 
26
- @dummy_form = DummyForm.new
27
- end
50
+ context 'when the class name method returns the class name' do
51
+ it 'uses the name method to guess the model name' do
52
+ form = Class.new { include SuperForm }
53
+ form.stub(:name).and_return 'InexistentForm'
28
54
 
29
- context 'when a field is defined at class level' do
30
- before(:all) { @fields = DummyForm.fields }
31
-
32
- it 'stores the basic field objects at class level' do
33
- expect(@fields.fetch(:name)).to be_instance_of Field::Text
34
- expect(@fields.fetch(:ball)).to be_instance_of Field::Null
35
- expect(@fields.fetch(:car)).to be_instance_of Field::Text
36
- end
55
+ expect(form).to receive(:name)
37
56
 
38
- it 'assigns the fieldset to the field' do
39
- expect(@fields.fetch(:name).fieldset).to eq :general
40
- expect(@fields.fetch(:ball).fieldset).to eq :toys
41
- expect(@fields.fetch(:car).fieldset).to eq :toys
57
+ form.model_name
58
+ end
59
+
60
+ it 'returns the correct model name' do
61
+ form = Class.new { include SuperForm }
62
+ form.stub(:name).and_return('InexistentForm')
63
+
64
+ expect(form.model_name.name).to eq 'Inexistent'
65
+ end
42
66
  end
43
67
  end
44
68
 
45
- context 'when a form object is created' do
46
- before(:each) { @dummy_form = DummyForm.new }
69
+ context 'when fields and fieldsets are defined' do
70
+ let!(:dummy) { form_with_fields }
47
71
 
48
- # this can get better, but for now it's ok
49
72
  it 'creates virtus attributes' do
50
- expect(@dummy_form).to respond_to(:name)
51
- expect(@dummy_form).to respond_to(:name=)
52
- expect(@dummy_form).to respond_to(:ball)
53
- expect(@dummy_form).to respond_to(:ball=)
54
- expect(@dummy_form).to respond_to(:car)
55
- expect(@dummy_form).to respond_to(:car=)
73
+ expect(dummy).to respond_to(:name)
74
+ expect(dummy).to respond_to(:name=)
75
+ expect(dummy).to respond_to(:ball)
76
+ expect(dummy).to respond_to(:ball=)
77
+ expect(dummy).to respond_to(:car)
78
+ expect(dummy).to respond_to(:car=)
79
+ expect(dummy).to respond_to(:email)
80
+ expect(dummy).to respond_to(:email=)
81
+ expect(dummy).to respond_to(:phone)
82
+ expect(dummy).to respond_to(:phone=)
56
83
  end
57
84
 
58
- it 'assigns the fieldset id to the field' do
59
- expect(@dummy_form.field(:name).fieldset).to eq :general
60
- expect(@dummy_form.field(:ball).fieldset).to eq :toys
61
- expect(@dummy_form.field(:car).fieldset).to eq :toys
85
+ it 'is ready for validation' do
86
+ expect(dummy).to_not be_valid
87
+ expect(dummy.errors[:name]).to eq ["can't be blank"]
88
+ expect(dummy.errors[:phone]).to eq ["is too short (minimum is 4 characters)"]
62
89
  end
63
90
 
64
- it 'defines fieldsets containing the bundled fields' do
65
- general = @dummy_form.fieldsets.fetch(:general)
91
+ it 'calls persisted! when a valid form is saved' do
92
+ dummy.name = 'Dummy'
93
+ dummy.phone = '12345'
66
94
 
67
- expect(general.first).to be_instance_of Field::Text
68
- expect(general.first.name).to eq :name
95
+ expect(dummy).to receive(:persist!).once
96
+ dummy.save
97
+ end
98
+ end
69
99
 
70
- toys = @dummy_form.fieldsets.fetch(:toys)
100
+ context 'when callbacks are defined' do
101
+ it 'triggers callbacks for save' do
102
+ dummy = form_with_fields do
103
+ before_save :callback_call
104
+ after_save :callback_call
105
+ end
71
106
 
72
- expect(toys.first).to be_instance_of Field::Null
73
- expect(toys.first.name).to eq :ball
107
+ dummy.name = 'Dummy'
108
+ dummy.phone = '12345'
74
109
 
75
- expect(toys.last).to be_instance_of Field::Text
76
- expect(toys.last.name).to eq :car
110
+ expect(dummy).to receive(:callback_call).twice
111
+ dummy.save
77
112
  end
78
113
 
79
- it 'fieldsets fields are the same instance of fields' do
80
- @dummy_form.fieldsets.each do |id, fields|
81
- fields.each do |field|
82
- expect(field).to eq @dummy_form.field(field.name)
83
- end
114
+ it 'triggers callbacks for validation' do
115
+ dummy = form_with_fields do
116
+ before_validation :callback_call
117
+ after_validation :callback_call
84
118
  end
119
+
120
+ dummy.name = 'Dummy'
121
+ dummy.phone = '12345'
122
+
123
+ expect(dummy).to receive(:callback_call).twice
124
+ dummy.valid?
85
125
  end
126
+ end
127
+ end
86
128
 
87
- it 'is ready for validation' do
88
- expect(@dummy_form).to_not be_valid
89
- expect(@dummy_form.errors[:name]).to eq ["can't be blank"]
129
+ def form_with_fields(&block)
130
+ Class.new do
131
+ include SuperForm
132
+
133
+ fieldset :general do
134
+ field :name, Field::Text, presence: true
90
135
  end
91
136
 
92
- context 'when assigning a new attribute' do
93
- it 'assigns the value of the attribute to the field' do
94
- pending
95
- end
137
+ fieldset :toys do
138
+ field :ball, Field::Bare
139
+ field :car, Field::Text
96
140
  end
97
- end
141
+
142
+ field :email, Field::Text
143
+ field :phone, Field::Text, length: { minimum: 4 }
144
+
145
+ instance_eval(&block) if block_given?
146
+ end.new
147
+ end
148
+
149
+ def form_with_no_fields
150
+ Class.new do
151
+ include SuperForm
152
+ end.new
98
153
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'telephone'
3
+
4
+ describe Telephone do
5
+ it "returns true if valid" do
6
+ valid_numbers = ['8436429999', '(84) 1111-1111', '8498741122']
7
+
8
+ valid_numbers.each do |number|
9
+ telephone = Telephone.new(number)
10
+ expect(telephone).to be_valid
11
+ end
12
+ end
13
+
14
+ it "returns false if not valid" do
15
+ invalid_numbers = ['843649999', '843 aaa', 'aaa 1234 $%']
16
+
17
+ invalid_numbers.each do |number|
18
+ telephone = Telephone.new(number)
19
+ expect(telephone).to_not be_valid
20
+ end
21
+ end
22
+
23
+ it "returns a stripped number" do
24
+ telephone = Telephone.new('(84) 3642-9999')
25
+ expect(telephone.stripped).to eq('8436429999')
26
+ end
27
+
28
+ it "returns a formatted number" do
29
+ telephone = Telephone.new('84 3642-9999')
30
+ expect(telephone.formatted).to eq('(84) 3642-9999')
31
+ end
32
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,17 +1,10 @@
1
- # This file was generated by the `rspec --init` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # Require this file using `require "spec_helper"` to ensure that it is only
4
- # loaded once.
5
- #
6
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
1
+ require 'pry'
2
+
7
3
  RSpec.configure do |config|
8
4
  config.treat_symbols_as_metadata_keys_with_true_values = true
9
5
  config.run_all_when_everything_filtered = true
10
6
  config.filter_run :focus
11
-
12
- # Run specs in random order to surface order dependencies. If you find an
13
- # order dependency and want to debug it, you can fix the order by providing
14
- # the seed, which is printed after each run.
15
- # --seed 1234
16
7
  config.order = 'random'
17
8
  end
9
+
10
+ I18n.enforce_available_locales = false if defined?(I18n)
@@ -0,0 +1,28 @@
1
+ shared_examples "presenter nameable" do
2
+ describe '.name' do
3
+ it 'returns a demodulized and underscored presenter name' do
4
+ presenter = Class.new(described_class) do
5
+ def self.name
6
+ 'Presenter::Deep::IDontExist'
7
+ end
8
+ end
9
+
10
+ expect(presenter.__name__).to eq 'i_dont_exist'
11
+ end
12
+
13
+ it 'trims _presenter suffix' do
14
+ presenter = Class.new(described_class) do
15
+ def self.name
16
+ 'Presenter::Deep::IDontExistPresenter'
17
+ end
18
+ end
19
+
20
+ expect(presenter.__name__).to eq 'i_dont_exist'
21
+ end
22
+
23
+ it 'raises an exception if presenter is anonymous' do
24
+ presenter = Class.new(described_class)
25
+ expect { presenter.__name__ }.to raise_error RuntimeError
26
+ end
27
+ end
28
+ end
data/super_form.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency 'rspec', '2.14.1'
25
25
  spec.add_development_dependency 'simplecov', '0.8.2'
26
26
  spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'pry', '0.9.12.6'
27
28
  spec.add_development_dependency 'capybara', '2.2.0'
28
29
  spec.add_development_dependency 'activemodel', '4.0.2'
29
30
  spec.add_development_dependency 'activesupport', '4.0.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: super_form
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thiago A. Silva
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-09 00:00:00.000000000 Z
11
+ date: 2014-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sqlite3
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 0.9.12.6
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 0.9.12.6
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: capybara
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -191,24 +205,53 @@ files:
191
205
  - lib/cnpj_validator.rb
192
206
  - lib/cpf_validator.rb
193
207
  - lib/field.rb
208
+ - lib/field/bare.rb
194
209
  - lib/field/base.rb
195
210
  - lib/field/cnpj.rb
196
211
  - lib/field/cpf.rb
197
212
  - lib/field/email.rb
198
213
  - lib/field/error.rb
214
+ - lib/field/float.rb
215
+ - lib/field/form.rb
216
+ - lib/field/form_array.rb
217
+ - lib/field/form_proxy.rb
199
218
  - lib/field/password.rb
200
219
  - lib/field/person_type.rb
201
220
  - lib/field/telephone.rb
202
221
  - lib/field/text.rb
203
222
  - lib/person_type.rb
223
+ - lib/presenter.rb
224
+ - lib/presenter/cnpj.rb
225
+ - lib/presenter/cpf.rb
226
+ - lib/presenter/form.rb
227
+ - lib/presenter/password.rb
228
+ - lib/presenter/person_type.rb
229
+ - lib/presenter/telephone.rb
204
230
  - lib/super_form.rb
231
+ - lib/super_form/fieldable.rb
232
+ - lib/super_form/fieldset.rb
205
233
  - lib/super_form/version.rb
206
234
  - lib/tasks/.keep
207
235
  - lib/telephone.rb
208
236
  - lib/telephone_validator.rb
209
237
  - lib/uniqueness_validator.rb
238
+ - spec/lib/field/form_array.rb
239
+ - spec/lib/field/form_array_spec.rb
240
+ - spec/lib/field/form_spec.rb
241
+ - spec/lib/field_spec.rb
242
+ - spec/lib/person_type_spec.rb
243
+ - spec/lib/presenter/cnpj_spec.rb
244
+ - spec/lib/presenter/cpf_spec.rb
245
+ - spec/lib/presenter/form_spec.rb
246
+ - spec/lib/presenter/password_spec.rb
247
+ - spec/lib/presenter/person_type_spec.rb
248
+ - spec/lib/presenter/telephone_spec.rb
249
+ - spec/lib/presenter_spec.rb
250
+ - spec/lib/super_form/fieldable_spec.rb
210
251
  - spec/lib/super_form_spec.rb
252
+ - spec/lib/telephone_spec.rb
211
253
  - spec/spec_helper.rb
254
+ - spec/support/presenter_name.rb
212
255
  - super_form.gemspec
213
256
  homepage: http://github.com/thiagoa/super_form
214
257
  licenses:
@@ -235,6 +278,21 @@ signing_key:
235
278
  specification_version: 4
236
279
  summary: Object oriented forms for Rails
237
280
  test_files:
281
+ - spec/lib/field/form_array.rb
282
+ - spec/lib/field/form_array_spec.rb
283
+ - spec/lib/field/form_spec.rb
284
+ - spec/lib/field_spec.rb
285
+ - spec/lib/person_type_spec.rb
286
+ - spec/lib/presenter/cnpj_spec.rb
287
+ - spec/lib/presenter/cpf_spec.rb
288
+ - spec/lib/presenter/form_spec.rb
289
+ - spec/lib/presenter/password_spec.rb
290
+ - spec/lib/presenter/person_type_spec.rb
291
+ - spec/lib/presenter/telephone_spec.rb
292
+ - spec/lib/presenter_spec.rb
293
+ - spec/lib/super_form/fieldable_spec.rb
238
294
  - spec/lib/super_form_spec.rb
295
+ - spec/lib/telephone_spec.rb
239
296
  - spec/spec_helper.rb
297
+ - spec/support/presenter_name.rb
240
298
  has_rdoc: