act_form 0.4.4 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d93ee18c0209358b5bfdd5f8bab5c31b9065ed223a901de2b5a45db192c7eb7a
4
- data.tar.gz: 6db591154d02ccb5407ee4cb615de83ef1337891cd8dda2f611c7bb6fe4b8522
3
+ metadata.gz: cab0f4f82ad6b6e33c6375695d4a74b54e26e3039583e2b1949ff6690de56832
4
+ data.tar.gz: b6f3dcdabe79a4a0777cae6e38ea4ce4d7c969eae81c3404abc3739f9c7c5026
5
5
  SHA512:
6
- metadata.gz: 5baa5bcdd152bbc018e1d9faa6df224290af67c98064297636e3fedc69b38c626dd0a442076a32ccac199a88915a7a4725ed076c97af8fce7a16f48565b1b78e
7
- data.tar.gz: dccf8fa34e9e10965207b87227ba687926732c27086f59bbe0e5e82bd2d056521ef6399fd7558457a2b3cb9ad8b36cf72dd3489d667ac5ee90dd68634dd7daa9
6
+ metadata.gz: f4746eb8bc9a2483114fce51de1f71d69c68a7cade4c0508cc8506126f73efb6a77703f3f242730ed5027f160dd13cf03b48d986958d9b7b7a0d427fd00da344
7
+ data.tar.gz: 4434f45ef372a6bfaca7e9627aabff63c1054e78d69bc9b694a37fdc255b62715aa50d5ea12e897615b994d0c12e7ce5d4268264ab096d25db5897a0aec8724e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,44 @@
1
+ # 0.5.0
2
+ * [Feature] issue#7 add more attribute type
3
+ * [Feature] issue#3 add `combine` DEPRECATION
4
+
5
+ With the power of `dry-schema`, ActForm now can support all the features of `dry-schema`, like:
6
+
7
+ ```ruby
8
+ class UserForm < ActForm::Base
9
+ params do
10
+ required(:name).filled.desc('Name')
11
+ optional(:age).value(:integer).desc('Age')
12
+ optional(:address).desc('Address')
13
+ optional(:nickname).default('nick').desc('Nick')
14
+ # below will support in the future
15
+ # attribute :desc, default: ->{ 'desc' }
16
+ end
17
+ end
18
+ ```
19
+
20
+ Add we can integrate with `grape` easyly.
21
+
22
+ ```ruby
23
+ module WorkWithGrapeSpec
24
+ class API < Grape::API
25
+ format :json
26
+
27
+ contract UserForm.contract
28
+ get '/foo' do
29
+ 'hello world'
30
+ end
31
+
32
+ contract FooService.contract do
33
+ required(:desc).filled
34
+ end
35
+ get '/bar' do
36
+ 'hello world'
37
+ end
38
+ end
39
+ end
40
+ ```
41
+
1
42
  # 0.4.4
2
43
  * [Fix] fix `setup` run before `required` validation
3
44
 
data/Gemfile CHANGED
@@ -4,5 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  group :development, :test do
7
+ gem 'grape', '>= 1.8.0'
7
8
  gem 'pry'
9
+ gem 'rack-test', '~> 2.1'
8
10
  end
data/README.md CHANGED
@@ -2,6 +2,45 @@
2
2
 
3
3
  ActForm is the gem that provide a simple way to create `form object` or `command object` or `service object`, it only depends on `activemodel >= 5` and provides few api.
4
4
 
5
+ ## About v0.5.0
6
+
7
+ With the power of `dry-schema`, ActForm now can support all the features of `dry-schema`, like:
8
+
9
+ ```ruby
10
+ class UserForm < ActForm::Base
11
+ params do
12
+ required(:name).filled.desc('Name')
13
+ optional(:age).value(:integer).desc('Age')
14
+ optional(:address).desc('Address')
15
+ optional(:nickname).default('nick').desc('Nick')
16
+ # below will support in the future
17
+ # attribute :desc, default: ->{ 'desc' }
18
+ end
19
+ end
20
+ ```
21
+
22
+ Add we can integrate with `grape` easyly.
23
+
24
+ ```ruby
25
+ module WorkWithGrapeSpec
26
+ class API < Grape::API
27
+ format :json
28
+
29
+ contract UserForm.contract
30
+ get '/foo' do
31
+ 'hello world'
32
+ end
33
+
34
+ contract UserForm.contract do
35
+ required(:desc).filled
36
+ end
37
+ get '/bar' do
38
+ 'hello world'
39
+ end
40
+ end
41
+ end
42
+ ```
43
+
5
44
  ## Usage
6
45
 
7
46
  #### API - `attribute`
@@ -191,14 +230,17 @@ Or install it yourself as:
191
230
 
192
231
  $ gem install act_form
193
232
 
194
-
195
233
  ## Development
196
234
 
197
235
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
198
236
 
237
+ ### Unit Tests
238
+
239
+ $ bundle exec rake test
240
+
199
241
  ## Contributing
200
242
 
201
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/act_form. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
243
+ Bug reports and pull requests are welcome on GitHub at https://github.com/simple-and-powerful/act_form. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
202
244
 
203
245
 
204
246
  ## License
data/act_form.gemspec CHANGED
@@ -1,5 +1,4 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'act_form/version'
5
4
 
@@ -9,8 +8,8 @@ Gem::Specification.new do |spec|
9
8
  spec.authors = ['zires']
10
9
  spec.email = ['zshuaibin@gmail.com']
11
10
 
12
- spec.summary = %q{A simple way to create form/command/service objects.}
13
- spec.description = %q{The simple way to create form objects or command/service objects with ActiveModel.}
11
+ spec.summary = 'A simple way to create form/command/service objects.'
12
+ spec.description = 'The simple way to create form objects or command/service objects with ActiveModel.'
14
13
  spec.homepage = 'https://github.com/simple-and-powerful/act-form'
15
14
  spec.license = 'MIT'
16
15
 
@@ -27,6 +26,7 @@ Gem::Specification.new do |spec|
27
26
  spec.require_paths = ['lib']
28
27
 
29
28
  spec.add_runtime_dependency 'activemodel', '>= 5.0.0'
29
+ spec.add_runtime_dependency 'dry-schema', '>= 1.13.4'
30
30
 
31
31
  spec.add_development_dependency 'bundler', '~> 2.1'
32
32
  spec.add_development_dependency 'rake', '~> 13.0'
@@ -34,7 +34,9 @@ module ActForm
34
34
  end
35
35
 
36
36
  class_methods do
37
+ # <b>DEPRECATED:</b> Please use <tt>ruby pure module</tt> instead.
37
38
  def combine(*forms)
39
+ warn '[DEPRECATION] `combine` is deprecated and will be removed in future versions. Instead, please use a pure Ruby module approach. For more details, refer to [link to migration guide].' # rubocop:disable Layout/LineLength
38
40
  forms.each do |form_class|
39
41
  raise ArgumentError, "can't combine itself" if form_class == self
40
42
 
@@ -0,0 +1,5 @@
1
+ zh-CN:
2
+ errors:
3
+ messages:
4
+ required: "是一个必填项"
5
+
@@ -8,7 +8,7 @@ module ActForm
8
8
  def merge_attribute_set_from(other)
9
9
  other.attribute_set.each do |attr_name, arr|
10
10
  cast_type, options = arr
11
- attribute attr_name, cast_type, options
11
+ attribute attr_name, cast_type, **options
12
12
  end
13
13
  end
14
14
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'active_model'
4
4
  require 'act_form/attributes'
5
+ require 'act_form/schema'
5
6
  require 'act_form/merge'
6
7
  require 'act_form/combinable'
7
8
 
@@ -11,10 +12,12 @@ module ActForm
11
12
  include ActiveModel::Model
12
13
  include ActiveModel::Validations::Callbacks
13
14
  include Attributes
15
+ include Schema
14
16
  include Merge
15
17
 
16
18
  included do
17
19
  set_callback :validation, :before, :validate_required_attributes
20
+ set_callback :validation, :before, :validate_contract
18
21
  end
19
22
 
20
23
  def initialize(attrs = {})
@@ -71,6 +74,17 @@ module ActForm
71
74
  throw(:abort) unless errors.empty?
72
75
  end
73
76
 
77
+ def validate_contract
78
+ return if self.class._schema.nil?
79
+
80
+ result = self.class._schema.validate(self.attributes)
81
+ return if result.success?
82
+
83
+ result.errors(full: true).each do |err|
84
+ errors.add(err.path.first, :invalid, message: err.text)
85
+ end
86
+ end
87
+
74
88
  class_methods do
75
89
  def inherited(child_class)
76
90
  child_class.include Combinable
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActForm
4
+ module Schema
5
+ class Base # rubocop:disable Style/Documentation
6
+ attr_reader :ins
7
+
8
+ def initialize(*parents, &block)
9
+ parent_arr = parents.map(&:contract)
10
+ @ins = ::Dry::Schema.Params(parent: parent_arr, &block)
11
+ @json = @ins.json_schema(loose: true)
12
+ @defaults = @ins.schema_dsl.defaults
13
+ @descriptions = @ins.schema_dsl.descriptions
14
+ end
15
+
16
+ def each # rubocop:disable Metrics/AbcSize
17
+ @ins.key_map.each do |key|
18
+ name = key.name.to_sym
19
+ opts = {
20
+ required: @json[:required].include?(key.name)
21
+ }
22
+ opts[:default] = @defaults[name] if @defaults.key?(name)
23
+ t = @json[:properties].dig(name, :type)
24
+ t = if t.is_a?(Array)
25
+ :object
26
+ else
27
+ t ? t.to_sym : :object
28
+ end
29
+ opts[:type] = t
30
+ yield name, opts
31
+ end
32
+ end
33
+
34
+ def validate(attrs)
35
+ _attrs = {}.merge!(attrs)
36
+ _attrs.merge!(@defaults)
37
+ @ins.call(_attrs)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActForm
4
+ module Schema
5
+ module Extensions
6
+ # Add defaults and descriptions to schema_dsl
7
+ module DSLExtension
8
+ def defaults
9
+ @_defaults ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName
10
+ end
11
+
12
+ def descriptions
13
+ @_descriptions ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName
14
+ end
15
+ end
16
+
17
+ # Add default and desc macros
18
+ module MacrosExtension
19
+ def default(value)
20
+ schema_dsl.defaults[name] = value
21
+ self
22
+ end
23
+
24
+ def desc(value)
25
+ schema_dsl.descriptions[name] = value
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActForm
4
+ module Schema # rubocop:disable Style/Documentation
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :_schema, instance_accessor: false
9
+ self._schema = nil
10
+ end
11
+
12
+ module ClassMethods # rubocop:disable Style/Documentation
13
+ def contract
14
+ self._schema.ins
15
+ end
16
+
17
+ def params(*parents, &block)
18
+ self._schema = Base.new(*parents, &block)
19
+ self._schema.each { |k, opts| self.attribute(k, **opts) }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActForm
4
- VERSION = '0.4.4'
4
+ VERSION = '0.5.0'
5
5
  end
data/lib/act_form.rb CHANGED
@@ -4,6 +4,14 @@ require 'act_form/version'
4
4
  require 'act_form/model'
5
5
  require 'act_form/runnable'
6
6
 
7
+ require 'dry/schema'
8
+ Dry::Schema.load_extensions(:json_schema)
9
+
10
+ require 'act_form/schema/base'
11
+ require 'act_form/schema/extensions'
12
+ ::Dry::Schema::DSL.include(::ActForm::Schema::Extensions::DSLExtension)
13
+ ::Dry::Schema::Macros::DSL.include(::ActForm::Schema::Extensions::MacrosExtension)
14
+
7
15
  module ActForm
8
16
  class Base
9
17
  include Model
@@ -17,3 +25,4 @@ module ActForm
17
25
  end
18
26
 
19
27
  I18n.load_path << "#{File.dirname(__FILE__)}/act_form/locale/en.yml"
28
+ I18n.load_path << "#{File.dirname(__FILE__)}/act_form/locale/zh-CN.yml"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: act_form
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - zires
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-02 00:00:00.000000000 Z
11
+ date: 2024-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 5.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: dry-schema
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.13.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.13.4
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -73,16 +87,20 @@ files:
73
87
  - lib/act_form/attributes.rb
74
88
  - lib/act_form/combinable.rb
75
89
  - lib/act_form/locale/en.yml
90
+ - lib/act_form/locale/zh-CN.yml
76
91
  - lib/act_form/merge.rb
77
92
  - lib/act_form/model.rb
78
93
  - lib/act_form/runnable.rb
94
+ - lib/act_form/schema.rb
95
+ - lib/act_form/schema/base.rb
96
+ - lib/act_form/schema/extensions.rb
79
97
  - lib/act_form/type.rb
80
98
  - lib/act_form/version.rb
81
99
  homepage: https://github.com/simple-and-powerful/act-form
82
100
  licenses:
83
101
  - MIT
84
102
  metadata: {}
85
- post_install_message:
103
+ post_install_message:
86
104
  rdoc_options: []
87
105
  require_paths:
88
106
  - lib
@@ -97,8 +115,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
115
  - !ruby/object:Gem::Version
98
116
  version: '0'
99
117
  requirements: []
100
- rubygems_version: 3.0.3
101
- signing_key:
118
+ rubygems_version: 3.5.1
119
+ signing_key:
102
120
  specification_version: 4
103
121
  summary: A simple way to create form/command/service objects.
104
122
  test_files: []