ree_lib 1.0.35 → 1.0.37

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 +11 -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 +7 -7
  18. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +7 -2
  19. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory.rb +20 -13
  20. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory_proxy.rb +2 -2
  21. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/abstract_type.rb +0 -15
  22. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/float.rb +2 -0
  23. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper.rb +1 -1
  24. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +77 -20
  25. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_spec.rb +25 -1
  26. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/float_spec.rb +9 -0
  27. data/lib/ree_lib/packages/ree_object/package/ree_object/functions/to_hash.rb +5 -3
  28. data/lib/ree_lib/packages/ree_object/spec/ree_object/functions/to_hash_spec.rb +5 -0
  29. data/lib/ree_lib/packages/ree_roda/.gitignore +0 -0
  30. data/lib/ree_lib/packages/ree_roda/.rspec +2 -0
  31. data/lib/ree_lib/packages/ree_roda/Package.schema.json +58 -0
  32. data/lib/ree_lib/packages/ree_roda/bin/console +5 -0
  33. data/lib/ree_lib/packages/ree_roda/package/ree_roda/app.rb +46 -0
  34. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_actions.rb +150 -0
  35. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_logger.rb +66 -0
  36. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_action_errors.rb +76 -0
  37. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_swagger_from_actions.rb +55 -0
  38. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/status_from_error.rb +25 -0
  39. data/lib/ree_lib/packages/ree_roda/package/ree_roda.rb +19 -0
  40. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_action_errors.schema.json +28 -0
  41. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_swagger_from_actions.schema.json +63 -0
  42. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/status_from_error.schema.json +28 -0
  43. data/lib/ree_lib/packages/ree_roda/spec/package_schema_spec.rb +14 -0
  44. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/app_spec.rb +84 -0
  45. data/lib/ree_lib/packages/ree_roda/spec/spec_helper.rb +3 -0
  46. data/lib/ree_lib/packages/ree_swagger/spec/functions/build_serializer_schema_spec.rb +8 -11
  47. data/lib/ree_lib/packages/ree_swagger/spec/functions/register_type_spec.rb +2 -7
  48. data/lib/ree_lib/version.rb +1 -1
  49. metadata +60 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 190a7da138d373c34c6e7636265ccce86c37e6ad5fd0c02b4e3c81c7e376393a
4
- data.tar.gz: ad6b89d186eec9a9006cc6d217ee82d6f20a34428bd052953aac7e2624a6b41c
3
+ metadata.gz: bfa479493ff3b8d80a181db242e9f443324b5c7f46b3629dae816f06eb2fd758
4
+ data.tar.gz: 371e0a229e967c47f8ad61de6c86aba1bb0e0b17651bf6447e7727734629e294
5
5
  SHA512:
6
- metadata.gz: 45199483809ad7917a207699df3acd7689db5dd246dfdce7910a7427a4d100750196a903b51aba2e24d0594141a01b8086e0767f9427b555fa2bdece22e83491
7
- data.tar.gz: d20668755d3da265a0ec0351220dfe9604cfaf21ebbb78833b093445afd01280e7b6e7d83ebba428b3808c346754fb1debcbed29197098f136c3b1a30bb24369
6
+ metadata.gz: 71b4a7f35d1a0569af42794acf8bf8c1193cf390ca773fd6ebab395cb86192199496812c9ae356e29a299a453304d6c25217cd20d9bd7884ded1e10fa798d68f
7
+ data.tar.gz: c5b3cf9ea44d8012ea7be12cf8ef9f33ac735a28c8d9bb384bf69fec6f8bc7932b7a1cf6f43be4439d7fa220b3cc2e630d8e0816b75c732fcb9b13e3e1b6ef22
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.0.35)
4
+ ree_lib (1.0.37)
5
5
  binding_of_caller (~> 1.0.0)
6
6
  i18n (~> 1.12.0)
7
7
  loofah (~> 2.18.0)
@@ -36,17 +36,24 @@ GEM
36
36
  crass (~> 1.0.2)
37
37
  nokogiri (>= 1.5.9)
38
38
  msgpack (1.6.0)
39
+ nokogiri (1.14.2-x86_64-darwin)
40
+ racc (~> 1.4)
39
41
  nokogiri (1.14.2-x86_64-linux)
40
42
  racc (~> 1.4)
41
43
  oj (3.13.23)
42
44
  pg (1.4.6)
43
45
  public_suffix (5.0.1)
44
46
  racc (1.6.2)
47
+ rack (3.0.5)
48
+ rack-test (2.0.2)
49
+ rack (>= 1.3)
45
50
  rainbow (3.1.1)
46
51
  rake (13.0.6)
47
- ree (1.0.23)
52
+ ree (1.0.27)
48
53
  commander (~> 4.6.0)
49
54
  rexml (3.2.5)
55
+ roda (3.58.0)
56
+ rack
50
57
  rollbar (3.3.3)
51
58
  rspec (3.12.0)
52
59
  rspec-core (~> 3.12.0)
@@ -79,8 +86,10 @@ PLATFORMS
79
86
  DEPENDENCIES
80
87
  bootsnap
81
88
  pg (~> 1.4.1)
89
+ rack-test
82
90
  rake (~> 13.0)
83
91
  ree_lib!
92
+ roda (~> 3.58.0)
84
93
  rollbar (~> 3.3.1)
85
94
  rspec
86
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
@@ -18,13 +18,13 @@ class ReeMapper::BuildMapperFactory
18
18
  @strategies = strategies
19
19
  }
20
20
 
21
- klass.register(:bool, Mapper.build(strategies, ReeMapper::Bool.new))
22
- klass.register(:date_time, Mapper.build(strategies, ReeMapper::DateTime.new))
23
- klass.register(:time, Mapper.build(strategies, ReeMapper::Time.new))
24
- klass.register(:date, Mapper.build(strategies, ReeMapper::Date.new))
25
- klass.register(:float, Mapper.build(strategies, ReeMapper::Float.new))
26
- klass.register(:integer, Mapper.build(strategies, ReeMapper::Integer.new))
27
- klass.register(:string, Mapper.build(strategies, ReeMapper::String.new))
21
+ klass.register_type(:bool, ReeMapper::Bool.new)
22
+ klass.register_type(:date_time, ReeMapper::DateTime.new)
23
+ klass.register_type(:time, ReeMapper::Time.new)
24
+ klass.register_type(:date, ReeMapper::Date.new)
25
+ klass.register_type(:float, ReeMapper::Float.new)
26
+ klass.register_type(:integer, ReeMapper::Integer.new)
27
+ klass.register_type(:string, ReeMapper::String.new)
28
28
 
29
29
  klass
30
30
  end
@@ -7,7 +7,7 @@ class ReeMapper::Mapper
7
7
  strategies.each do |strategy|
8
8
  method = strategy.method
9
9
  next if type.respond_to?(method)
10
- raise ReeMapper::UnsupportedTypeError, "type #{type.name} should implement method `#{method}`"
10
+ raise ReeMapper::UnsupportedTypeError, "type #{type.inspect} should implement method `#{method}`"
11
11
  end
12
12
  end
13
13
 
@@ -113,7 +113,7 @@ class ReeMapper::Mapper
113
113
 
114
114
  contract(Symbol => Class).throws(ArgumentError)
115
115
  def dto(strategy_method)
116
- strategy = strategies.detect { _1.method == strategy_method }
116
+ strategy = find_strategy(strategy_method)
117
117
  raise ArgumentError, "there is no :#{strategy_method} strategy" unless strategy
118
118
  strategy.dto
119
119
  end
@@ -124,4 +124,9 @@ class ReeMapper::Mapper
124
124
  strategies.each { _1.prepare_dto(fields.keys) }
125
125
  nil
126
126
  end
127
+
128
+ contract(Symbol => Nilor[ReeMapper::MapperStrategy])
129
+ def find_strategy(strategy_method)
130
+ strategies.detect { _1.method == strategy_method }
131
+ end
127
132
  end
@@ -5,35 +5,42 @@ class ReeMapper::MapperFactory
5
5
  attr_reader :types, :strategies
6
6
  end
7
7
 
8
- contract(Symbol, Any => Class).throws(ArgumentError)
9
- def self.register_type(name, object_type)
10
- register(
8
+ contract(Symbol => Nilor[ReeMapper::MapperStrategy])
9
+ def self.find_strategy(strategy_method)
10
+ strategies.detect { _1.method == strategy_method }
11
+ end
12
+
13
+ contract(Symbol, ReeMapper::AbstractType, Kwargs[strategies: ArrayOf[ReeMapper::MapperStrategy]] => Class)
14
+ def self.register_type(name, object_type, strategies: self.strategies)
15
+ register_mapper(
11
16
  name,
12
17
  ReeMapper::Mapper.build(strategies, object_type)
13
18
  )
14
19
  end
15
20
 
16
- contract(Symbol, Any => Class).throws(ArgumentError)
17
- def self.register(name, type)
18
- raise ArgumentError, "name of mapper type should not include `?`" if name.to_s.end_with?('?')
19
- raise ArgumentError, "type :#{name} already registered" if types.key?(name)
20
- raise ArgumentError, "method :#{name} already defined" if method_defined?(name)
21
+ contract(Symbol, ReeMapper::Mapper => Class).throws(ArgumentError)
22
+ def self.register_mapper(name, type)
23
+ raise ArgumentError, "name of mapper type should not end with `?`" if name.to_s.end_with?('?')
24
+
25
+ defined_strategy_method = types[name]&.flat_map(&:strategy_methods)&.detect { type.find_strategy(_1) }
26
+ raise ArgumentError, "type :#{name} with `#{defined_strategy_method}` strategy already registered" if defined_strategy_method
27
+ raise ArgumentError, "method :#{name} already defined" if !types.key?(name) && method_defined?(name)
21
28
 
22
29
  type = type.dup
23
30
  type.name = name
24
31
  type.freeze
25
- types[name] = type
32
+ types[name] ||= []
33
+ types[name] << type
26
34
 
27
35
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
28
36
  def #{name}(field_name = nil, optional: false, **opts)
29
37
  raise ReeMapper::Error, "invalid DSL usage" unless @mapper
30
38
  raise ArgumentError, "array item can't be optional" if field_name.nil? && optional
31
39
 
32
- type = self.class.types.fetch(:#{name})
40
+ type = self.class.types.fetch(:#{name}).detect { (@mapper.strategy_methods - _1.strategy_methods).empty? }
33
41
 
34
- @mapper.strategy_methods.each do |method|
35
- next if type.respond_to?(method)
36
- raise ReeMapper::UnsupportedTypeError, "type :#{name} should implement method `\#{method}`"
42
+ unless type
43
+ raise ReeMapper::UnsupportedTypeError, "type :#{name} should implement `\#{@mapper.strategy_methods.join(', ')}`"
37
44
  end
38
45
 
39
46
  return ReeMapper::Field.new(type, optional: optional, **opts) unless field_name
@@ -22,7 +22,7 @@ class ReeMapper::MapperFactoryProxy
22
22
  if strategy_or_method.is_a?(ReeMapper::MapperStrategy)
23
23
  strategy = strategy_or_method
24
24
  else
25
- strategy = mapper_factory.strategies.detect { _1.method == strategy_or_method }
25
+ strategy = mapper_factory.find_strategy(strategy_or_method)
26
26
  raise ArgumentError, "MapperFactory strategy :#{strategy_or_method} not found" unless strategy
27
27
  strategy = strategy.dup
28
28
  strategy.dto = dto if dto
@@ -36,7 +36,7 @@ class ReeMapper::MapperFactoryProxy
36
36
  mapper_factory.new(mapper).instance_exec(&blk)
37
37
  mapper.prepare_dto
38
38
 
39
- mapper_factory.register(register_as, mapper) if register_as
39
+ mapper_factory.register_mapper(register_as, mapper) if register_as
40
40
 
41
41
  after_build&.call(mapper)
42
42
 
@@ -1,17 +1,2 @@
1
1
  class ReeMapper::AbstractType
2
- def serialize(value, name:, role: nil)
3
- raise NotImplementedError
4
- end
5
-
6
- def cast(value, name:, role: nil)
7
- raise NotImplementedError
8
- end
9
-
10
- def db_dump(value, name:, role: nil)
11
- raise NotImplementedError
12
- end
13
-
14
- def db_load(value, name:, role: nil)
15
- raise NotImplementedError
16
- end
17
2
  end