active_dry_form 0.1.0 → 1.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.
@@ -1,129 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveDryForm
4
- class Form
4
+ class Form < BaseForm
5
5
 
6
6
  include Dry::Monads[:result]
7
- Dry::Schema.load_extensions(:info)
7
+ Dry::Schema.load_extensions(:json_schema)
8
8
  ResultError = Class.new(StandardError)
9
9
 
10
- class ContractBase < Dry::Validation::Contract
10
+ cattr_accessor :contract_klass, instance_accessor: false, default: ::ActiveDryForm::BaseContract
11
11
 
12
- config.messages.load_paths << 'config/locales/dry_validation.ru.yml'
13
- config.messages.default_locale = :ru
12
+ def self.fields(namespace, i18n_key: nil, &block)
13
+ const_set :CURRENT_CONTRACT, Class.new(contract_klass, &block).new
14
+ const_set :FIELDS_INFO, self::CURRENT_CONTRACT.schema.json_schema(loose: true)
14
15
 
15
- end
16
-
17
- def self.fields(namespace, &block)
18
- const_set :NAMESPACE, ActiveModel::Name.new(nil, nil, namespace.to_s)
19
- const_set :CURRENT_CONTRACT, Class.new(ContractBase, &block).new
20
- const_set :FIELDS_INFO, self::CURRENT_CONTRACT.schema.info[:keys]
21
-
22
- self::FIELDS_INFO.each do |key, value|
23
- if value[:keys]
24
- sub_klass = Class.new do
25
- const_set :NAMESPACE, ActiveModel::Name.new(nil, nil, key.to_s)
26
- const_set :FIELDS_INFO, value[:keys]
27
-
28
- def initialize(params, record, errors)
29
- @params = params || {}
30
- @record = record
31
- @errors = errors || {}
32
- end
33
-
34
- self::FIELDS_INFO.each_key do |sub_key|
35
- define_method sub_key do
36
- @params[sub_key] || @record.try(sub_key)
37
- end
38
-
39
- def model_name
40
- self.class::NAMESPACE
41
- end
42
-
43
- def info(sub_key)
44
- self.class::FIELDS_INFO[sub_key]
45
- end
16
+ const_set :NAMESPACE, ActiveModel::Name.new(nil, nil, namespace.name.capitalize)
17
+ const_get(:NAMESPACE).i18n_key = i18n_key if i18n_key
46
18
 
47
- # ActionView::Helpers::Tags::Translator#human_attribute_name
48
- def to_model
49
- self
50
- end
51
-
52
- def self.human_attribute_name(field)
53
- I18n.t(field, scope: :"activerecord.attributes.#{self::NAMESPACE.i18n_key}")
54
- end
55
-
56
- def errors
57
- @errors
58
- end
59
- end
60
- end
61
- define_method key do
62
- sub_klass.new(@params[key], @record.try(key), errors[key])
63
- end
64
- else
65
- define_method key do
66
- @params[key] || @record.try(key)
67
- end
68
- end
69
- end
70
- end
71
-
72
- def self.default(method)
73
- alias_method :"__#{method}", method
74
-
75
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
76
- # def create_default(...)
77
- # @params.merge!(__create_default(...))
78
- # end
79
-
80
- def #{method}(...)
81
- @params.merge!(__#{method}(...))
82
- end
83
- RUBY
19
+ define_methods
84
20
  end
85
21
 
86
22
  def self.action(method)
87
23
  alias_method :"__#{method}", method
88
24
 
89
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
90
- # def create(...)
91
- # if validator.failure?
92
- # @base_errors = validator.errors.filter(:base?).map(&:to_s).presence
93
- # return Failure(:validate_invalid)
94
- # end
95
- #
96
- # result = __create(...)
97
- #
98
- # unless result.is_a?(::Dry::Monads::Result)
99
- # raise ResultError, 'method `create` should be returning `monad`'
100
- # end
101
- #
102
- # case result
103
- # in Failure[:failure_service, base_errors]
104
- # @base_errors = base_errors
105
- # else
106
- # end
107
- #
108
- # result
109
- # end
110
-
25
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1 # rubocop:disable Style/DocumentDynamicEvalDefinition
111
26
  def #{method}(...)
112
- if validator.failure?
113
- @base_errors = validator.errors.filter(:base?).map(&:to_s).presence
114
- return Failure(:validate_invalid)
115
- end
27
+ validate
28
+ return Failure(:invalid_form) unless valid?
116
29
 
117
30
  result = __#{method}(...)
118
31
 
119
- unless result.is_a?(::Dry::Monads::Result)
120
- raise ResultError, 'method `#{method}` should be returning `monad`'
121
- end
122
-
123
32
  case result
124
- in Failure[:failure_service, base_errors]
125
- @base_errors = base_errors
33
+ when ::Dry::Monads::Result::Failure
34
+ @base_errors = Array.wrap(result.failure)
35
+ when ::Dry::Monads::Result::Success
126
36
  else
37
+ raise ResultError, 'method `#{method}` must return `monad`'
127
38
  end
128
39
 
129
40
  result
@@ -131,81 +42,5 @@ module ActiveDryForm
131
42
  RUBY
132
43
  end
133
44
 
134
- attr_reader :base_errors, :record
135
-
136
- def initialize(record: nil, params_form: nil, params_init: nil)
137
- raise 'in `params_form` use `request.parameters` instead of `params`' if params_form.is_a?(::ActionController::Parameters)
138
- raise 'in `params_init` use `request.parameters` instead of `params`' if params_init.is_a?(::ActionController::Parameters)
139
-
140
- @params =
141
- if params_form
142
- _deep_transform_values_in_params!(params_form[self.class::NAMESPACE.param_key].deep_transform_keys!(&:to_sym))
143
- elsif params_init
144
- params_init.deep_transform_keys!(&:to_sym)
145
- else
146
- {}
147
- end
148
-
149
- @record = record if record
150
- end
151
-
152
- def info(key)
153
- self.class::FIELDS_INFO[key]
154
- end
155
-
156
- def model_name
157
- self.class::NAMESPACE
158
- end
159
-
160
- # ActionView::Helpers::Tags::Translator#human_attribute_name
161
- def to_model
162
- self
163
- end
164
-
165
- def self.human_attribute_name(field)
166
- I18n.t(field, scope: :"activerecord.attributes.#{self::NAMESPACE.i18n_key}")
167
- end
168
-
169
- def persisted?
170
- @record&.persisted?
171
- end
172
-
173
- def to_key
174
- key = @record&.id
175
- [key] if key
176
- end
177
-
178
- # используется при генерации URL, когда record.persisted?
179
- def to_param
180
- @record.id.to_s
181
- end
182
-
183
- def validator
184
- @validator ||= self.class::CURRENT_CONTRACT.call(@params, { form: self })
185
- end
186
-
187
- def errors
188
- @errors ||= @validator ? @validator.errors.to_h : {}
189
- end
190
-
191
- def view_component
192
- self.class.module_parent::Component.new(self)
193
- end
194
-
195
- private def _deep_transform_values_in_params!(object)
196
- case object
197
- when String
198
- object.strip.presence
199
- when Hash
200
- object.transform_values! { |value| _deep_transform_values_in_params!(value) }
201
- when Array
202
- object.map! { |e| _deep_transform_values_in_params!(e) }
203
- object.compact!
204
- object
205
- else
206
- object
207
- end
208
- end
209
-
210
45
  end
211
46
  end
@@ -3,14 +3,21 @@
3
3
  module ActiveDryForm
4
4
  module FormHelper
5
5
 
6
- def active_dry_form_for(name, options = {})
6
+ def active_dry_form_for(name, options = {}, &block)
7
7
  options[:builder] = ActiveDryForm::Builder
8
- options[:html] ||= {}
9
- options[:html][:class] = "active-dry-form #{options[:html][:class]}"
8
+ options[:html] = html_options(options)
10
9
 
11
10
  form_for(name, options) do |f|
12
11
  concat f.show_base_errors
13
- yield(f)
12
+ instance_exec(f, &block)
13
+ end
14
+ end
15
+
16
+ private def html_options(options)
17
+ classes = { class: ActiveDryForm.config.css_classes.form }
18
+
19
+ (options[:html] || {}).merge(ActiveDryForm.config.html_options.form, classes) do |_key, oldval, newval|
20
+ Array.wrap(newval) + Array.wrap(oldval)
14
21
  end
15
22
  end
16
23
 
@@ -3,37 +3,32 @@
3
3
  module ActiveDryForm
4
4
  class Input
5
5
 
6
- attr_reader :input_opts, :input_type
7
-
8
- def initialize(builder, method_type, method, options)
6
+ def initialize(builder, builder_method, field, options)
9
7
  @builder = builder
10
- @method_type = method_type
11
- @method = method
8
+ @form_object = builder.object
9
+ @template = builder.instance_variable_get(:@template)
12
10
 
13
- info = builder.object.info(method)
14
- @input_type = info[:type]
15
- @required = info[:required]
11
+ @builder_method = builder_method
12
+ @field = field
16
13
 
17
14
  @label_opts = options[:label]
18
15
  @label_text = options[:label_text]
19
16
  @hint_text = options[:hint]
20
- @input_opts = options.except(:label, :hint, :label_text)
21
- @input_opts[:required] = true if @required
17
+ @required = options[:required]
18
+ @input_user_options = options.except(:label, :hint, :label_text)
22
19
  end
23
20
 
24
21
  def css_classes
25
22
  [
26
- 'input',
27
- @method_type,
28
- @input_type,
29
- @method,
30
- ('required' if @required),
31
- ('error' if error?(@method)),
23
+ ActiveDryForm.config.css_classes.input,
24
+ @builder_method,
25
+ (ActiveDryForm.config.css_classes.input_required if @required),
26
+ (ActiveDryForm.config.css_classes.input_error if error?(@field)),
32
27
  ].compact
33
28
  end
34
29
 
35
30
  def wrap_tag(input, label_last: nil)
36
- @builder.tag.div class: css_classes do
31
+ @template.tag(:div, class: css_classes) do
37
32
  [
38
33
  label_last ? input : label,
39
34
  label_last ? label : input,
@@ -44,29 +39,29 @@ module ActiveDryForm
44
39
  end
45
40
 
46
41
  def label
47
- @builder.label(@method, @label_text) unless @label_opts == false
42
+ @builder.label(@field, @label_text) unless @label_opts == false
48
43
  end
49
44
 
50
45
  def hint_text
51
46
  return unless @hint_text
52
47
 
53
- @builder.tag.small @hint_text, class: 'help-text'
48
+ @template.content_tag(:small, @hint_text, class: ActiveDryForm.config.css_classes.hint)
54
49
  end
55
50
 
56
51
  def error_text
57
- return unless error?(@method)
52
+ return unless error?(@field)
58
53
 
59
54
  obj_error_text =
60
- case e = @builder.object.errors[@method]
55
+ case e = @form_object.errors[@field]
61
56
  when Hash then e.values
62
57
  else e
63
58
  end
64
59
 
65
- @builder.tag.div obj_error_text.join('<br />'), class: 'form-error is-visible'
60
+ @template.content_tag(:div, obj_error_text.join('<br />').html_safe, class: ActiveDryForm.config.css_classes.error)
66
61
  end
67
62
 
68
- def error?(method)
69
- @builder.object.errors.key?(method)
63
+ def error?(field)
64
+ @form_object.errors.key?(field)
70
65
  end
71
66
 
72
67
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveDryForm
4
- VERSION = "0.1.0"
4
+
5
+ VERSION = '1.1.0'
6
+
5
7
  end
@@ -1,13 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "active_dry_form/version"
4
- require_relative "active_dry_form/schema_compiler_patch"
5
- require_relative "active_dry_form/builder"
6
- require_relative "active_dry_form/form"
7
- require_relative "active_dry_form/input"
8
- require_relative "active_dry_form/form_helper"
3
+ require 'dry-monads'
4
+ require 'dry-validation'
5
+ require 'active_model'
6
+ require 'action_view'
7
+ require 'action_controller'
8
+
9
+ require_relative 'active_dry_form/version'
10
+ require_relative 'active_dry_form/configuration'
11
+ require_relative 'active_dry_form/builder'
12
+ require_relative 'active_dry_form/base_form'
13
+ require_relative 'active_dry_form/base_contract'
14
+ require_relative 'active_dry_form/form'
15
+ require_relative 'active_dry_form/input'
16
+ require_relative 'active_dry_form/form_helper'
9
17
 
10
18
  module ActiveDryForm
19
+
11
20
  class Error < StandardError; end
12
- # Your code goes here...
21
+ class ParamsNotAllowedError < Error; end
22
+ class DateTimeNotAllowedError < Error; end
23
+
13
24
  end
metadata CHANGED
@@ -1,17 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_dry_form
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ermolaev Andrey
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-20 00:00:00.000000000 Z
11
+ date: 2024-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: dry-validation
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dry-configurable
15
43
  requirement: !ruby/object:Gem::Requirement
16
44
  requirements:
17
45
  - - ">="
@@ -38,6 +66,20 @@ dependencies:
38
66
  - - ">="
39
67
  - !ruby/object:Gem::Version
40
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dry-validation
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
41
83
  description: Form validation for Rails with Dry-Validation
42
84
  email:
43
85
  - andruhafirst@yandex.ru
@@ -48,18 +90,23 @@ files:
48
90
  - ".editorconfig"
49
91
  - ".rspec"
50
92
  - ".rubocop.yml"
93
+ - ".tool-versions"
51
94
  - Gemfile
95
+ - Gemfile.lock
52
96
  - LICENSE.txt
53
97
  - README.md
54
98
  - Rakefile
55
99
  - bin/console
56
100
  - bin/setup
101
+ - config/locales/dry_validation.ru.yml
57
102
  - lib/active_dry_form.rb
103
+ - lib/active_dry_form/base_contract.rb
104
+ - lib/active_dry_form/base_form.rb
58
105
  - lib/active_dry_form/builder.rb
106
+ - lib/active_dry_form/configuration.rb
59
107
  - lib/active_dry_form/form.rb
60
108
  - lib/active_dry_form/form_helper.rb
61
109
  - lib/active_dry_form/input.rb
62
- - lib/active_dry_form/schema_compiler_patch.rb
63
110
  - lib/active_dry_form/version.rb
64
111
  homepage: https://github.com/corp-gp/active_dry_form
65
112
  licenses:
@@ -68,7 +115,8 @@ metadata:
68
115
  allowed_push_host: https://rubygems.org
69
116
  homepage_uri: https://github.com/corp-gp/active_dry_form
70
117
  source_code_uri: https://github.com/corp-gp/active_dry_form
71
- post_install_message:
118
+ rubygems_mfa_required: 'true'
119
+ post_install_message:
72
120
  rdoc_options: []
73
121
  require_paths:
74
122
  - lib
@@ -76,15 +124,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
76
124
  requirements:
77
125
  - - ">="
78
126
  - !ruby/object:Gem::Version
79
- version: 2.6.0
127
+ version: 2.7.0
80
128
  required_rubygems_version: !ruby/object:Gem::Requirement
81
129
  requirements:
82
130
  - - ">="
83
131
  - !ruby/object:Gem::Version
84
132
  version: '0'
85
133
  requirements: []
86
- rubygems_version: 3.1.6
87
- signing_key:
134
+ rubygems_version: 3.3.17
135
+ signing_key:
88
136
  specification_version: 4
89
137
  summary: Form validation for Rails with Dry-Validation
90
138
  test_files: []
@@ -1,31 +0,0 @@
1
- require "dry/schema/extensions/info/schema_compiler"
2
-
3
- require "dry/schema/constants"
4
-
5
- module Dry
6
- module Schema
7
- module Info
8
- class SchemaCompiler
9
- def visit_not(_node, opts = {})
10
- key = opts[:key]
11
- keys[key][:nullable] = true
12
- end
13
-
14
- def visit_predicate(node, opts = {})
15
- name, rest = node
16
-
17
- key = opts[:key]
18
-
19
- if name.equal?(:key?)
20
- keys[rest[0][1]] = { required: opts.fetch(:required, true) }
21
- elsif name.equal?(:array?)
22
- keys[key][:array] = true
23
- else
24
- type = PREDICATE_TO_TYPE[name]
25
- keys[key][:type] = type if type
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end