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.
- checksums.yaml +4 -4
- data/lib/field.rb +15 -9
- data/lib/field/bare.rb +3 -0
- data/lib/field/base.rb +54 -15
- data/lib/field/cnpj.rb +5 -7
- data/lib/field/cpf.rb +6 -8
- data/lib/field/email.rb +4 -4
- data/lib/field/float.rb +7 -0
- data/lib/field/form.rb +30 -0
- data/lib/field/form_array.rb +32 -0
- data/lib/field/form_proxy.rb +16 -0
- data/lib/field/password.rb +6 -10
- data/lib/field/person_type.rb +0 -4
- data/lib/field/telephone.rb +2 -7
- data/lib/person_type.rb +2 -8
- data/lib/presenter.rb +90 -0
- data/lib/presenter/cnpj.rb +9 -0
- data/lib/presenter/cpf.rb +9 -0
- data/lib/presenter/form.rb +20 -0
- data/lib/presenter/password.rb +7 -0
- data/lib/presenter/person_type.rb +9 -0
- data/lib/presenter/telephone.rb +9 -0
- data/lib/super_form.rb +21 -156
- data/lib/super_form/fieldable.rb +78 -0
- data/lib/super_form/fieldset.rb +32 -0
- data/lib/super_form/version.rb +1 -1
- data/spec/lib/field/form_array.rb +71 -0
- data/spec/lib/field/form_array_spec.rb +71 -0
- data/spec/lib/field/form_spec.rb +68 -0
- data/spec/lib/field_spec.rb +13 -0
- data/spec/lib/person_type_spec.rb +66 -0
- data/spec/lib/presenter/cnpj_spec.rb +9 -0
- data/spec/lib/presenter/cpf_spec.rb +9 -0
- data/spec/lib/presenter/form_spec.rb +39 -0
- data/spec/lib/presenter/password_spec.rb +8 -0
- data/spec/lib/presenter/person_type_spec.rb +8 -0
- data/spec/lib/presenter/telephone_spec.rb +9 -0
- data/spec/lib/presenter_spec.rb +166 -0
- data/spec/lib/super_form/fieldable_spec.rb +82 -0
- data/spec/lib/super_form_spec.rb +120 -65
- data/spec/lib/telephone_spec.rb +32 -0
- data/spec/spec_helper.rb +4 -11
- data/spec/support/presenter_name.rb +28 -0
- data/super_form.gemspec +1 -0
- metadata +60 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61ec845a89d382bcafc1395324d331ca94e86e78
|
4
|
+
data.tar.gz: de0a636fc0d8b72884d35ff42f6593c54d1791a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,
|
3
|
-
autoload :Base,
|
4
|
-
autoload :Text,
|
5
|
-
autoload :
|
6
|
-
autoload :
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
autoload :
|
10
|
-
autoload :
|
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
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
|
9
|
-
|
10
|
-
@fieldset = fieldset
|
7
|
+
def self.factory(*args)
|
8
|
+
new(*args)
|
11
9
|
end
|
12
10
|
|
13
|
-
def
|
14
|
-
|
11
|
+
def initialize(name, options = {})
|
12
|
+
@name = name
|
13
|
+
@options = options
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
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
|
-
|
24
|
-
false
|
23
|
+
inject_validations
|
25
24
|
end
|
26
25
|
|
27
26
|
def attribute
|
28
27
|
String
|
29
28
|
end
|
30
29
|
|
31
|
-
def
|
32
|
-
|
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
|
7
|
-
|
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
|
-
|
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 <
|
6
|
-
def
|
7
|
-
|
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
|
-
|
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
|
6
|
-
|
7
|
-
|
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
|
-
|
25
|
+
@container.validates name, uniqueness: options[:uniqueness].merge(required)
|
26
26
|
options.reject! { |k| k == :uniqueness }
|
27
27
|
end
|
28
28
|
|
data/lib/field/float.rb
ADDED
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
|
data/lib/field/password.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
1
|
module Field
|
2
2
|
class Password < Base
|
3
|
-
def
|
4
|
-
|
3
|
+
def inject_attributes
|
4
|
+
@container.attribute :"#{name}_confirmation", String
|
5
5
|
|
6
6
|
super
|
7
7
|
end
|
8
8
|
|
9
|
-
def add_validations
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
data/lib/field/person_type.rb
CHANGED
data/lib/field/telephone.rb
CHANGED
@@ -3,8 +3,8 @@ require 'telephone_validator'
|
|
3
3
|
|
4
4
|
module Field
|
5
5
|
class Telephone < Base
|
6
|
-
def
|
7
|
-
|
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
|