ree_lib 1.0.36 → 1.0.38

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +9 -2
  3. data/lib/ree_lib/Packages.schema.json +8 -0
  4. data/lib/ree_lib/packages/ree_actions/.gitignore +0 -0
  5. data/lib/ree_lib/packages/ree_actions/.rspec +2 -0
  6. data/lib/ree_lib/packages/ree_actions/Package.schema.json +20 -0
  7. data/lib/ree_lib/packages/ree_actions/bin/console +5 -0
  8. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action.rb +10 -0
  9. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_builder.rb +65 -0
  10. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_dsl.rb +60 -0
  11. data/lib/ree_lib/packages/ree_actions/package/ree_actions/dsl.rb +102 -0
  12. data/lib/ree_lib/packages/ree_actions/package/ree_actions.rb +12 -0
  13. data/lib/ree_lib/packages/ree_actions/spec/package_schema_spec.rb +14 -0
  14. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/action_dsl_spec.rb +62 -0
  15. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/dsl_spec.rb +93 -0
  16. data/lib/ree_lib/packages/ree_actions/spec/spec_helper.rb +3 -0
  17. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/functions/build_mapper_factory.rb +4 -0
  18. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +17 -10
  19. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory.rb +73 -35
  20. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/any.rb +23 -0
  21. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/abstract_wrapper.rb +8 -0
  22. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/{types → wrappers}/array.rb +10 -17
  23. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper.rb +5 -1
  24. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +62 -2
  25. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/any_spec.rb +47 -0
  26. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/type_options_spec.rb +4 -4
  27. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/{types → wrappers}/array_spec.rb +7 -7
  28. data/lib/ree_lib/packages/ree_roda/.gitignore +0 -0
  29. data/lib/ree_lib/packages/ree_roda/.rspec +2 -0
  30. data/lib/ree_lib/packages/ree_roda/Package.schema.json +58 -0
  31. data/lib/ree_lib/packages/ree_roda/bin/console +5 -0
  32. data/lib/ree_lib/packages/ree_roda/package/ree_roda/app.rb +46 -0
  33. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_actions.rb +150 -0
  34. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_logger.rb +66 -0
  35. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_action_errors.rb +76 -0
  36. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_swagger_from_actions.rb +55 -0
  37. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/status_from_error.rb +25 -0
  38. data/lib/ree_lib/packages/ree_roda/package/ree_roda.rb +19 -0
  39. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_action_errors.schema.json +28 -0
  40. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_swagger_from_actions.schema.json +63 -0
  41. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/status_from_error.schema.json +28 -0
  42. data/lib/ree_lib/packages/ree_roda/spec/package_schema_spec.rb +14 -0
  43. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/app_spec.rb +84 -0
  44. data/lib/ree_lib/packages/ree_roda/spec/spec_helper.rb +3 -0
  45. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/beans/type_definitions_repo.rb +1 -1
  46. data/lib/ree_lib/packages/ree_swagger/spec/functions/build_parameters_spec.rb +1 -1
  47. data/lib/ree_lib/packages/ree_swagger/spec/functions/build_serializer_schema_spec.rb +3 -3
  48. data/lib/ree_lib/version.rb +1 -1
  49. metadata +65 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61b5c4cb5d7eef9fc932ebe3a674c5c752cb82d035248910a8a3da7a1ffe45b5
4
- data.tar.gz: d604e93726df4c19ebfe4c244a9d91da836e2a587d8599969bd9e5980a4e07d9
3
+ metadata.gz: 9f94479d9a955ba5ba5f65a8eba245bfab7c050b5a55e16a5de1773d920837bf
4
+ data.tar.gz: e45a2a8f9166d4ed50d3cbc58a3bb73cb026adf3b09a8b32f64af986c1e15bdb
5
5
  SHA512:
6
- metadata.gz: e05879958d07507dce29039623c4c88a5eb4b49ea7c9eee56b86346f004cbea2f455a42464142cc91d04aeefb07e65d3f2436073a3e58bcfd9434b6512cc8d31
7
- data.tar.gz: c5888ac8151e1016bde7705fdbdc13bc4f814007401ff23d9da9bac160810ca6e1b92008015b507e90a110035848189d6d291093b7fea42ca1df7d6c5f962c24
6
+ metadata.gz: 93db2ec2423d53c97f2ae8a43e989f18c9d6d47e062686d1f89d9f45c58b90eca0778eb6c7ed20f1f16a35d85af7474e3a230f89f437d146817539626df25bbf
7
+ data.tar.gz: fec05fa12a474168bc340ecf473a7cef26aa1ce8d7a0845e459c419228ddb954f52cacd35e4a4a58ca8ab7574218a47e274f55d4793e23c102801c81993b7c88
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.0.36)
4
+ ree_lib (1.0.38)
5
5
  binding_of_caller (~> 1.0.0)
6
6
  i18n (~> 1.12.0)
7
7
  loofah (~> 2.18.0)
@@ -44,11 +44,16 @@ GEM
44
44
  pg (1.4.6)
45
45
  public_suffix (5.0.1)
46
46
  racc (1.6.2)
47
+ rack (3.0.5)
48
+ rack-test (2.0.2)
49
+ rack (>= 1.3)
47
50
  rainbow (3.1.1)
48
51
  rake (13.0.6)
49
- ree (1.0.26)
52
+ ree (1.0.27)
50
53
  commander (~> 4.6.0)
51
54
  rexml (3.2.5)
55
+ roda (3.58.0)
56
+ rack
52
57
  rollbar (3.3.3)
53
58
  rspec (3.12.0)
54
59
  rspec-core (~> 3.12.0)
@@ -81,8 +86,10 @@ PLATFORMS
81
86
  DEPENDENCIES
82
87
  bootsnap
83
88
  pg (~> 1.4.1)
89
+ rack-test
84
90
  rake (~> 13.0)
85
91
  ree_lib!
92
+ roda (~> 3.58.0)
86
93
  rollbar (~> 3.3.1)
87
94
  rspec
88
95
  sqlite3 (~> 1.4.4)
@@ -2,6 +2,10 @@
2
2
  "schema_version": "1.0",
3
3
  "schema_type": "packages",
4
4
  "packages": [
5
+ {
6
+ "name": "ree_actions",
7
+ "schema": "packages/ree_actions/Package.schema.json"
8
+ },
5
9
  {
6
10
  "name": "ree_array",
7
11
  "schema": "packages/ree_array/Package.schema.json"
@@ -66,6 +70,10 @@
66
70
  "name": "ree_object",
67
71
  "schema": "packages/ree_object/Package.schema.json"
68
72
  },
73
+ {
74
+ "name": "ree_roda",
75
+ "schema": "packages/ree_roda/Package.schema.json"
76
+ },
69
77
  {
70
78
  "name": "ree_string",
71
79
  "schema": "packages/ree_string/Package.schema.json"
File without changes
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,20 @@
1
+ {
2
+ "schema_type": "package",
3
+ "schema_version": "1.1",
4
+ "name": "ree_actions",
5
+ "entry_path": "packages/ree_actions/package/ree_actions.rb",
6
+ "tags": [
7
+ "ree_actions"
8
+ ],
9
+ "depends_on": [
10
+ {
11
+ "name": "ree_mapper"
12
+ }
13
+ ],
14
+ "env_vars": [
15
+
16
+ ],
17
+ "objects": [
18
+
19
+ ]
20
+ }
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+ require "ree"
4
+
5
+ Ree.init(__dir__, irb: true)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ReeActions::Action
4
+ attr_accessor :summary, :request_method, :serializer, :respond_to,
5
+ :sections, :action, :warden_scope, :path
6
+
7
+ def valid?
8
+ !@action.nil? && !summary.nil? && !warden_scope.nil?
9
+ end
10
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "action"
4
+
5
+ class ReeActions::ActionBuilder
6
+ Redirect = Struct.new(:path, :code)
7
+
8
+ def initialize
9
+ @action = ReeActions::Action.new
10
+ @action.respond_to = :json
11
+ end
12
+
13
+ contract Symbol => Symbol
14
+ def warden_scope(scope)
15
+ @action.warden_scope = scope
16
+ end
17
+
18
+ contract Symbol => Symbol
19
+ def respond_to(v)
20
+ @action.respond_to = v
21
+ end
22
+
23
+ contract None => ReeActions::Action
24
+ def get_action
25
+ @action
26
+ end
27
+
28
+ contract Block => nil
29
+ def before(&proc)
30
+ @action.before = proc
31
+ nil
32
+ end
33
+
34
+ contract String => String
35
+ def summary(str)
36
+ @action.summary = str
37
+ end
38
+
39
+ contract Symbol, Symbol => nil
40
+ def serializer(name, from:)
41
+ object = Ree.container.packages_facade.get_object(from, name)
42
+ @action.serializer = object
43
+ nil
44
+ end
45
+
46
+ contract SplatOf[String] => nil
47
+ def sections(*names)
48
+ @action.sections = names
49
+ nil
50
+ end
51
+
52
+ contract Symbol, Symbol => nil
53
+ def action(name, from:)
54
+ object = Ree.container.packages_facade.get_object(from, name)
55
+ @action.action = object
56
+ nil
57
+ end
58
+
59
+ contract String, Kwargs[code: Integer] => nil
60
+ def redirect(path, code: 301)
61
+ raise ArgumentError if ![301, 302, 303, 307, 308].include?(code)
62
+ @action.redirect = Redirect.new(path, code)
63
+ nil
64
+ end
65
+ end
@@ -0,0 +1,60 @@
1
+ module ReeActions
2
+ module ActionDSL
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ base.include(ReeMapper::DSL)
6
+ end
7
+
8
+ def self.extended(base)
9
+ base.extend(ClassMethods)
10
+ base.include(ReeMapper::DSL)
11
+ end
12
+
13
+ module ClassMethods
14
+ include Ree::Contracts::Core
15
+ include Ree::Contracts::ArgContracts
16
+
17
+ def action(name, &proc)
18
+ dsl = Ree::ObjectDsl.new(
19
+ Ree.container.packages_facade, name, self, :fn
20
+ )
21
+
22
+ dsl.instance_exec(&proc) if block_given?
23
+ dsl.tags(["action"])
24
+ dsl.freeze(false)
25
+ dsl.object.set_as_compiled(false)
26
+
27
+ Ree.container.compile(dsl.package, name)
28
+ end
29
+
30
+ def method_added(method_name)
31
+ return super if method_name != :call
32
+
33
+ if @__original_call_defined
34
+ remove_instance_variable(:@__original_call_defined)
35
+ return
36
+ end
37
+
38
+ @__original_call_defined = true
39
+
40
+ alias_method(:__original_call, :call)
41
+
42
+ define_method :call do |user_access, attrs|
43
+ if self.class.const_defined?(:ActionCaster)
44
+ caster = self.class.const_get(:ActionCaster)
45
+
46
+ if !caster.respond_to?(:cast)
47
+ raise ArgumentError.new("ActionCaster does not respond to `cast` method")
48
+ end
49
+
50
+ __original_call(user_access, caster.cast(attrs))
51
+ else
52
+ __original_call(user_access, attrs)
53
+ end
54
+ end
55
+
56
+ nil
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "action_builder"
4
+ require "uri"
5
+
6
+ module ReeActions
7
+ module DSL
8
+ def self.included(base)
9
+ base.extend(ClassMethods)
10
+ end
11
+
12
+ def self.extended(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+
16
+ module FactoryMethod
17
+ def build
18
+ self.class.instance_variable_get(:@actions) || []
19
+ end
20
+ end
21
+
22
+ module ClassMethods
23
+ include Ree::Contracts::Core
24
+ include Ree::Contracts::ArgContracts
25
+
26
+ def actions(name, &proc)
27
+ raise ArgumentError.new("block is required") if !block_given?
28
+
29
+ @dsl = Ree::ObjectDsl.new(
30
+ Ree.container.packages_facade, name, self, :object
31
+ )
32
+
33
+ @dsl.singleton
34
+ @dsl.factory(:build)
35
+ @dsl.tags(["actions"])
36
+
37
+ instance_exec(&proc)
38
+
39
+ klass = @dsl.object.klass
40
+ klass.send(:include, FactoryMethod)
41
+
42
+
43
+ Ree.container.compile(@dsl.package, name)
44
+ end
45
+
46
+ def default_warden_scope(method_name)
47
+ @default_warden_scope = method_name
48
+ end
49
+
50
+ [:get, :post, :put, :delete, :patch, :head, :options].each do |request_method|
51
+ define_method request_method do |path, &proc|
52
+ define_action(request_method, path, &proc)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ contract Symbol, String, Block => ReeActions::Action
59
+ def define_action(request_method, path, &proc)
60
+ raise ArgumentError.new("actions should be called") if !@dsl
61
+ raise ArgumentError.new("block is required") if !block_given?
62
+
63
+ @actions ||= []
64
+
65
+ builder = ReeActions::ActionBuilder.new
66
+ builder.instance_exec(&proc)
67
+
68
+ if @default_warden_scope && !builder.get_action.warden_scope
69
+ builder.warden_scope(@default_warden_scope)
70
+ end
71
+
72
+ uri = URI.parse(path) rescue nil
73
+
74
+ if uri.nil? || uri.path != path
75
+ raise ArgumentError.new("invalid path provided #{path}")
76
+ end
77
+
78
+ if uri.query && !uri.query.empty?
79
+ raise ArgumentError.new("action path should not include query params: #{path}")
80
+ end
81
+
82
+ builder.get_action.path = path
83
+ builder.get_action.request_method = request_method
84
+
85
+ if !builder.get_action.valid?
86
+ raise ArgumentError.new("action, summary and auth scope should be provider for #{builder.get_action.inspect}")
87
+ end
88
+
89
+ action = builder.get_action
90
+
91
+ @dsl.link(action.action.name, from: action.action.package_name)
92
+
93
+ if action.serializer
94
+ @dsl.link(action.serializer.name, from: action.serializer.package_name)
95
+ end
96
+
97
+ @actions << action
98
+ action
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReeActions
4
+ include Ree::PackageDSL
5
+
6
+ package do
7
+ depends_on :ree_mapper
8
+ end
9
+ end
10
+
11
+ require_relative "ree_actions/dsl"
12
+ require_relative "ree_actions/action_dsl"
@@ -0,0 +1,14 @@
1
+ RSpec.describe "ReeActions" do
2
+ it "generates package schema" do
3
+ require "fileutils"
4
+
5
+ packages_schema_path = Ree.locate_packages_schema(__dir__)
6
+ packages_schema_dir = Pathname.new(packages_schema_path).dirname.to_s
7
+
8
+ FileUtils.cd packages_schema_dir do
9
+ expect(
10
+ system("REE_SKIP_ENV_VARS_CHECK=true bundle exec ree gen.package_json ree_actions --silence")
11
+ ).to eq(true)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,62 @@
1
+ package_require("ree_actions/action_dsl")
2
+
3
+ RSpec.describe ReeActions::ActionDSL, type: [:autoclean] do
4
+ before do
5
+ Ree.enable_irb_mode
6
+ end
7
+
8
+ after do
9
+ Ree.disable_irb_mode
10
+ end
11
+
12
+ it {
13
+ module ReeActionsTest
14
+ include Ree::PackageDSL
15
+
16
+ package do
17
+ depends_on :ree_mapper
18
+ end
19
+
20
+ class TestAction
21
+ include ReeActions::ActionDSL
22
+
23
+ action :test_action
24
+
25
+ ActionCaster = build_mapper.use(:cast) do
26
+ integer :user_id
27
+ end
28
+
29
+ contract Any, ActionCaster.dto(:cast) => Integer
30
+ def call(user_access, attrs)
31
+ attrs[:user_id]
32
+ end
33
+ end
34
+ end
35
+
36
+ result = ReeActionsTest::TestAction.new.call('user_access', {user_id: 1})
37
+ expect(result).to eq(1)
38
+ }
39
+
40
+ it {
41
+ module ReeActionsTest
42
+ include Ree::PackageDSL
43
+
44
+ package do
45
+ end
46
+
47
+ class TestAction2
48
+ include ReeActions::ActionDSL
49
+
50
+ action :test_action2
51
+
52
+ contract Any, Hash => Integer
53
+ def call(user_access, attrs)
54
+ attrs[:user_id]
55
+ end
56
+ end
57
+ end
58
+
59
+ result = ReeActionsTest::TestAction2.new.call('user_access', {user_id: 1})
60
+ expect(result).to eq(1)
61
+ }
62
+ end
@@ -0,0 +1,93 @@
1
+ package_require("ree_actions/dsl")
2
+
3
+ RSpec.describe ReeActions::DSL, type: [:autoclean] do
4
+ before :all do
5
+ Ree.enable_irb_mode
6
+
7
+ module ReeActionsTest
8
+ include Ree::PackageDSL
9
+
10
+ package
11
+ end
12
+
13
+ class ReeActionsTest::EmptyActions
14
+ include ReeActions::DSL
15
+
16
+ actions :empty_actions do
17
+ end
18
+ end
19
+
20
+ class ReeActionsTest::Cmd
21
+ include Ree::FnDSL
22
+
23
+ fn :cmd
24
+
25
+ def call
26
+ end
27
+ end
28
+
29
+ class ReeActionsTest::Serializer
30
+ include ReeMapper::DSL
31
+
32
+ mapper :serializer
33
+
34
+ build_mapper.use(:serialize) do
35
+ integer :id
36
+ end
37
+ end
38
+
39
+ class ReeActionsTest::Caster
40
+ include ReeMapper::DSL
41
+
42
+ mapper :caster
43
+
44
+ build_mapper.use(:cast) do
45
+ integer :id
46
+ end
47
+ end
48
+
49
+ class ReeActionsTest::Actions
50
+ include ReeActions::DSL
51
+
52
+ actions :actions do
53
+ default_warden_scope :user
54
+
55
+ post "users" do
56
+ summary "Test action"
57
+ action :cmd, from: :ree_actions_test
58
+ serializer :serializer, from: :ree_actions_test
59
+ respond_to :json
60
+ end
61
+
62
+ get "files.csv" do
63
+ summary "Test action"
64
+ action :cmd, from: :ree_actions_test
65
+ respond_to :csv
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ after :all do
72
+ Ree.disable_irb_mode
73
+ end
74
+
75
+ it {
76
+ expect(ReeActionsTest::EmptyActions.new).to eq([])
77
+ }
78
+
79
+ it {
80
+ actions = ReeActionsTest::Actions.new
81
+
82
+ expect(actions.size).to eq(2)
83
+
84
+ post_action = actions.first
85
+ csv_action = actions.last
86
+
87
+ expect(post_action.serializer.name).to eq(:serializer)
88
+ expect(post_action.action.name).to eq(:cmd)
89
+ expect(post_action.respond_to).to eq(:json)
90
+
91
+ expect(csv_action.respond_to).to eq(:csv)
92
+ }
93
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.extend Ree::RSpecLinkDSL
3
+ end
@@ -15,6 +15,7 @@ class ReeMapper::BuildMapperFactory
15
15
 
16
16
  klass.instance_eval {
17
17
  @types = {}
18
+ @wrappers = {}
18
19
  @strategies = strategies
19
20
  }
20
21
 
@@ -25,6 +26,9 @@ class ReeMapper::BuildMapperFactory
25
26
  klass.register_type(:float, ReeMapper::Float.new)
26
27
  klass.register_type(:integer, ReeMapper::Integer.new)
27
28
  klass.register_type(:string, ReeMapper::String.new)
29
+ klass.register_type(:any, ReeMapper::Any.new)
30
+
31
+ klass.register_wrapper(:array, ReeMapper::Array)
28
32
 
29
33
  klass
30
34
  end
@@ -1,13 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ReeMapper::Mapper
4
- contract(ArrayOf[ReeMapper::MapperStrategy], Nilor[ReeMapper::AbstractType] => Any).throws(ReeMapper::UnsupportedTypeError)
4
+ contract(
5
+ ArrayOf[ReeMapper::MapperStrategy],
6
+ Nilor[ReeMapper::AbstractType, ReeMapper::AbstractWrapper] => self
7
+ ).throws(ReeMapper::UnsupportedTypeError)
5
8
  def self.build(strategies, type = nil)
6
9
  if type
7
10
  strategies.each do |strategy|
8
11
  method = strategy.method
9
12
  next if type.respond_to?(method)
10
- raise ReeMapper::UnsupportedTypeError, "type #{type.inspect} should implement method `#{method}`"
13
+
14
+ raise ReeMapper::UnsupportedTypeError, "#{type.class} should implement method `#{method}`"
11
15
  end
12
16
  end
13
17
 
@@ -20,11 +24,13 @@ class ReeMapper::Mapper
20
24
  if type
21
25
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
22
26
  def #{method}(obj, name: nil, role: nil, only: nil, except: nil, fields_filters: [])
23
- if @type.is_a?(ReeMapper::Array)
24
- @type.#{method}(obj, name: name, role: role, fields_filters: fields_filters)
25
- else
26
- @type.#{method}(obj, name: name, role: role)
27
- end
27
+ #{
28
+ if type.is_a?(ReeMapper::AbstractWrapper)
29
+ "@type.#{method}(obj, name: name, role: role, fields_filters: fields_filters)"
30
+ else
31
+ "@type.#{method}(obj, name: name, role: role)"
32
+ end
33
+ }
28
34
  end
29
35
  RUBY
30
36
  else
@@ -95,9 +101,10 @@ class ReeMapper::Mapper
95
101
  end
96
102
  end
97
103
 
98
- contract(Any, Symbol, Ksplat[RestKeys => Any] => nil)
99
- def add_field(type, name, **opts)
100
- @fields[name] = ReeMapper::Field.new(type, name, **opts)
104
+ contract(ReeMapper::Field => nil)
105
+ def add_field(field)
106
+ raise ArgumentError if field.name.nil?
107
+ @fields[field.name] = field
101
108
  nil
102
109
  end
103
110