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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a5f0e95c7ffd7c811db1288e98272f0544bcacaa
4
- data.tar.gz: f5e6d6330f0524b513fdf6cf4b4305cf90e32a1d
3
+ metadata.gz: 61ec845a89d382bcafc1395324d331ca94e86e78
4
+ data.tar.gz: de0a636fc0d8b72884d35ff42f6593c54d1791a1
5
5
  SHA512:
6
- metadata.gz: 7617b22b0f8b2530b9ec7a08cc3ba3e79f7b87f3526a6f3ecadea596b9ccb2ccc45121afd5ada9a95b57ff87d42707638e3818b49c618c2e6e1d5cb1019c502c
7
- data.tar.gz: af71f75d3eb608ba7975890d02c9379a2f398c567720cc1e4e2997b5814101e58342acffbb6a5715b3a0f5828a7a62e69f5e1ea642fb1021a37b06b54d0ceb8b
6
+ metadata.gz: 2d10f75ebf0978ca8c0dec009fdfaeb9129fe814ece7b4646b064fd5ef59a3be5ec679bf8361ec2ad2c66a319e289f4c06189392df724ffe0fa2eaebf2e8ce23
7
+ data.tar.gz: f399675c1e2e55d1dcf1e299b42acf73502a05e3e035c8aae5fa20c2eb5c3736e86fda5a2bb4237d9dbe7c9ab337ac53ae06d683befd4d8a012336d3d4bcdbee
data/lib/field.rb CHANGED
@@ -1,11 +1,17 @@
1
+ require 'attribute'
2
+ require 'super_form/fieldset'
3
+
1
4
  module Field
2
- autoload :Error, 'field/error'
3
- autoload :Base, 'field/base'
4
- autoload :Text, 'field/text'
5
- autoload :Password, 'field/password'
6
- autoload :Email, 'field/email'
7
- autoload :CPF, 'field/cpf'
8
- autoload :CNPJ, 'field/cnpj'
9
- autoload :Telephone, 'field/telephone'
10
- autoload :PersonType, 'field/person_type'
5
+ autoload :Error, 'field/error'
6
+ autoload :Base, 'field/base'
7
+ autoload :Text, 'field/text'
8
+ autoload :Form, 'field/form'
9
+ autoload :FormArray, 'field/form_array'
10
+ autoload :Password, 'field/password'
11
+ autoload :Email, 'field/email'
12
+ autoload :Float, 'field/float'
13
+ autoload :CPF, 'field/cpf'
14
+ autoload :CNPJ, 'field/cnpj'
15
+ autoload :Telephone, 'field/telephone'
16
+ autoload :PersonType, 'field/person_type'
11
17
  end
data/lib/field/bare.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Field
2
+ class Bare < Base; end
3
+ end
data/lib/field/base.rb CHANGED
@@ -1,35 +1,74 @@
1
1
  module Field
2
2
  class Base
3
3
  attr_accessor :name
4
+ attr_accessor :options
4
5
  attr_accessor :form
5
- attr_accessor :value
6
- attr_reader :fieldset
7
6
 
8
- def initialize(name, fieldset)
9
- @name = name
10
- @fieldset = fieldset
7
+ def self.factory(*args)
8
+ new(*args)
11
9
  end
12
10
 
13
- def add_attributes(klass, options)
14
- klass.attribute name, self.attribute
11
+ def initialize(name, options = {})
12
+ @name = name
13
+ @options = options
15
14
  end
16
15
 
17
- def add_validations(klass, options)
18
- if options.any?
19
- klass.send(:validates, name, options)
16
+ def setup_container(container)
17
+ @container = container
18
+
19
+ if Helper.container_is_virtus?(container)
20
+ inject_attributes
20
21
  end
21
- end
22
22
 
23
- def form?
24
- false
23
+ inject_validations
25
24
  end
26
25
 
27
26
  def attribute
28
27
  String
29
28
  end
30
29
 
31
- def output
32
- value
30
+ def inject_attributes
31
+ @container.attribute @name, attribute
32
+ end
33
+
34
+ def inject_validations
35
+ if @options.any?
36
+ @container.send(:validates, @name, @options)
37
+ end
38
+ end
39
+
40
+ def value
41
+ @form.send(name) if @form
42
+ end
43
+
44
+ def presenter_class
45
+ nil
46
+ end
47
+ end
48
+
49
+ module Helper
50
+ def self.container_is_virtus?(container)
51
+ defined?(Virtus::Model::Core) &&
52
+ container.ancestors.include?(Virtus::Model::Core)
53
+ end
54
+ end
55
+
56
+ class Proxy
57
+ def initialize(options, &setup)
58
+ @options = options
59
+ @setup = setup
60
+ end
61
+
62
+ def factory(name, options = {})
63
+ @setup.call(name, options, self)
64
+ end
65
+
66
+ def method_missing(id, *args)
67
+ @options[id] || super
68
+ end
69
+
70
+ def respond_to_missing?(method_name, include_private = false)
71
+ @options.key? method_name
33
72
  end
34
73
  end
35
74
  end
data/lib/field/cnpj.rb CHANGED
@@ -3,8 +3,8 @@ require 'cnpj_validator'
3
3
 
4
4
  module Field
5
5
  class CNPJ < Base
6
- def add_validations(klass, options)
7
- klass.validates name, cnpj: true
6
+ def inject_validations
7
+ @container.validates name, cnpj: true
8
8
 
9
9
  if options[:uniqueness]
10
10
  unless options[:uniqueness].is_a?(Hash) && options[:uniqueness][:model]
@@ -17,7 +17,9 @@ module Field
17
17
  allow_blank: true
18
18
  }
19
19
 
20
- klass.validates name, uniqueness: options[:uniqueness].merge(required)
20
+ options[:uniqueness].merge!(required)
21
+ @container.validates name, uniqueness: options[:uniqueness]
22
+
21
23
  options.reject! { |k| k == :uniqueness }
22
24
  end
23
25
 
@@ -27,9 +29,5 @@ module Field
27
29
  def attribute
28
30
  ::Attribute::CNPJ
29
31
  end
30
-
31
- def output
32
- ::CNPJ.new(value).formatted
33
- end
34
32
  end
35
33
  end
data/lib/field/cpf.rb CHANGED
@@ -2,9 +2,9 @@ require 'cpf'
2
2
  require 'cpf_validator'
3
3
 
4
4
  module Field
5
- class CPF < ::Field::Base
6
- def add_validations(klass, options)
7
- klass.validates name, cpf: true
5
+ class CPF < Base
6
+ def inject_validations
7
+ @container.validates name, cpf: true
8
8
 
9
9
  if options[:uniqueness]
10
10
  unless options[:uniqueness].is_a?(Hash) && options[:uniqueness][:model]
@@ -17,7 +17,9 @@ module Field
17
17
  allow_blank: true
18
18
  }
19
19
 
20
- klass.validates name, uniqueness: options[:uniqueness].merge(required)
20
+ options[:uniqueness].merge!(required)
21
+ @container.validates name, uniqueness: options[:uniqueness]
22
+
21
23
  options.reject! { |k| k == :uniqueness }
22
24
  end
23
25
 
@@ -27,9 +29,5 @@ module Field
27
29
  def attribute
28
30
  ::Attribute::CPF
29
31
  end
30
-
31
- def output
32
- ::CPF.new(value).formatted
33
- end
34
32
  end
35
33
  end
data/lib/field/email.rb CHANGED
@@ -2,9 +2,9 @@ require 'validates_email_format_of'
2
2
 
3
3
  module Field
4
4
  class Email < Base
5
- def add_validations(klass, options)
6
- klass.validates name, length: { maximum: 155 }
7
- klass.validates name, email_format: {
5
+ def inject_validations
6
+ @container.validates name, length: { maximum: 155 }
7
+ @container.validates name, email_format: {
8
8
  message: I18n.t('activemodel.errors.messages.email'),
9
9
  allow_nil: true,
10
10
  allow_blank: true
@@ -22,7 +22,7 @@ module Field
22
22
  allow_blank: true
23
23
  }
24
24
 
25
- klass.validates name, uniqueness: options[:uniqueness].merge(required)
25
+ @container.validates name, uniqueness: options[:uniqueness].merge(required)
26
26
  options.reject! { |k| k == :uniqueness }
27
27
  end
28
28
 
@@ -0,0 +1,7 @@
1
+ module Field
2
+ class Float < Base
3
+ def attribute
4
+ Float
5
+ end
6
+ end
7
+ end
data/lib/field/form.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'field/form_proxy'
2
+
3
+ module Field
4
+ class Form < Base
5
+ extend FormProxy
6
+
7
+ attr_accessor :form_class
8
+
9
+ def inject_attributes
10
+ @container.attribute @name, attribute, default: attribute.new
11
+ end
12
+
13
+ def inject_validations
14
+ @container.class_eval %Q{
15
+ method = "__ensure_valid_#{name.to_s}__"
16
+ validate method
17
+
18
+ define_method method do
19
+ unless send('#{name}').send(:valid?)
20
+ errors.add(:base, "Invalid #{name.to_s}")
21
+ end
22
+ end
23
+ }
24
+ end
25
+
26
+ def attribute
27
+ @form_class
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ require 'field/form_proxy'
2
+
3
+ module Field
4
+ class FormArray < Base
5
+ extend FormProxy
6
+
7
+ attr_accessor :form_class
8
+
9
+ def inject_attributes
10
+ @container.attribute @name, attribute
11
+ end
12
+
13
+ def inject_validations
14
+ @container.class_eval %Q{
15
+ method = "__ensure_valid_#{name.to_s}__"
16
+ validate method
17
+
18
+ define_method method do
19
+ #{name}.each_with_index do |form, i|
20
+ unless form.send(:valid?)
21
+ errors.add(:base, "Invalid #{name.to_s} on row \#\{i + 1\}")
22
+ end
23
+ end
24
+ end
25
+ }
26
+ end
27
+
28
+ def attribute
29
+ Array[@form_class]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ module Field
2
+ module FormProxy
3
+ def [](form_class)
4
+ extra = {
5
+ form_class: form_class,
6
+ field_class: self
7
+ }
8
+
9
+ Proxy.new(extra) do |name, options, proxy|
10
+ field = proxy.field_class.new(name, options)
11
+ field.form_class = proxy.form_class
12
+ field
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,21 +1,17 @@
1
1
  module Field
2
2
  class Password < Base
3
- def add_attributes(klass, options)
4
- klass.attribute :"#{name}_confirmation", String
3
+ def inject_attributes
4
+ @container.attribute :"#{name}_confirmation", String
5
5
 
6
6
  super
7
7
  end
8
8
 
9
- def add_validations(klass, options)
10
- klass.validates name, presence: true, if: ->(f){ !f.to_param }
11
- klass.validates name, confirmation: true, if: ->(f){ !f.to_param }
12
- klass.validates name, length: { minimum: 5, maximum: 15 }, allow_blank: true
9
+ def add_validations
10
+ @container.validates name, presence: true, if: ->(f){ !f.to_param }
11
+ @container.validates name, confirmation: true, if: ->(f){ !f.to_param }
12
+ @container.validates name, length: { minimum: 5, maximum: 15 }, allow_blank: true
13
13
 
14
14
  super
15
15
  end
16
-
17
- def output
18
- nil
19
- end
20
16
  end
21
17
  end
@@ -5,9 +5,5 @@ module Field
5
5
  def attribute
6
6
  ::Attribute::PersonType
7
7
  end
8
-
9
- def output
10
- ::PersonType.new(value).description
11
- end
12
8
  end
13
9
  end
@@ -3,8 +3,8 @@ require 'telephone_validator'
3
3
 
4
4
  module Field
5
5
  class Telephone < Base
6
- def add_validations(klass, options)
7
- klass.validates name, telephone: true
6
+ def inject_validations
7
+ @container.validates name, telephone: true
8
8
 
9
9
  super
10
10
  end
@@ -12,10 +12,5 @@ module Field
12
12
  def attribute
13
13
  ::Attribute::Telephone
14
14
  end
15
-
16
- def output
17
- return unless value
18
- ::Telephone.new(value).formatted
19
- end
20
15
  end
21
16
  end
data/lib/person_type.rb CHANGED
@@ -14,8 +14,8 @@ class PersonType
14
14
  end
15
15
 
16
16
  def self.descriptions
17
- TYPES.each_with_object({}) do |type, hash|
18
- hash[type] = description(type)
17
+ TYPES.each_with_object({}) do |type, hash|
18
+ hash[type] = description(type)
19
19
  end
20
20
  end
21
21
 
@@ -42,10 +42,4 @@ class PersonType
42
42
  def to_s
43
43
  value
44
44
  end
45
-
46
- class Attribute < Virtus::Attribute
47
- def coerce(value)
48
- ::PersonType.new(value).value
49
- end
50
- end
51
45
  end
data/lib/presenter.rb ADDED
@@ -0,0 +1,90 @@
1
+ require 'delegate'
2
+ require 'active_support/inflector'
3
+
4
+ module Presenter
5
+ autoload :CPF, 'presenter/cpf'
6
+ autoload :CNPJ, 'presenter/cnpj'
7
+ autoload :Telephone, 'presenter/telephone'
8
+ autoload :Password, 'presenter/password'
9
+ autoload :PersonType, 'presenter/person_type'
10
+ autoload :Form, 'presenter/form'
11
+
12
+ module Name
13
+ def __name__
14
+ if name.nil?
15
+ raise 'You must define __name__ on a presenter anonymous class'
16
+ end
17
+
18
+ name.demodulize.underscore.gsub(/_presenter$/, '')
19
+ end
20
+ end
21
+
22
+ class Base < SimpleDelegator
23
+ extend Name
24
+
25
+ def self.map(params)
26
+ params.each { |p| setup_attribute(p) }
27
+ end
28
+
29
+ def self.use(*presenters)
30
+ params = presenters.each_with_object({}) do |id, p|
31
+ p[id] = id
32
+ end
33
+
34
+ map params
35
+ end
36
+
37
+ private
38
+
39
+ def self.setup_attribute(params)
40
+ attribute, presenter = params
41
+ presenter_name = presenter.is_a?(Class) ? presenter.__name__ : presenter
42
+ method = "#{presenter_name}_presenter"
43
+
44
+ def_presenter_accessor(presenter, method)
45
+ def_attribute_reader(attribute, method)
46
+ end
47
+
48
+ def self.def_presenter_accessor(presenter, method)
49
+ attr_writer method
50
+
51
+ define_method(method) do
52
+ instance_variable_get(:"@#{method}") ||
53
+ self.class.find_presenter(presenter)
54
+ end
55
+ end
56
+
57
+ def self.def_attribute_reader(attribute, presenter_method)
58
+ define_method(attribute) do
59
+ presenter = send(presenter_method)
60
+ presenter.value = __getobj__.send(attribute)
61
+ presenter.output
62
+ end
63
+ end
64
+
65
+ def self.find_presenter(presenter)
66
+ return presenter.new if presenter.is_a?(Class)
67
+
68
+ base_class = presenter.to_s.capitalize.camelize
69
+ Object.const_get("Presenter::#{base_class}").new
70
+ end
71
+ end
72
+
73
+ class Each
74
+ extend Name
75
+
76
+ attr_accessor :value
77
+
78
+ def initialize(value = nil)
79
+ self.value = value
80
+ end
81
+
82
+ def output
83
+ value
84
+ end
85
+
86
+ def to_s
87
+ output
88
+ end
89
+ end
90
+ end