yaks 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +158 -56
- data/Rakefile +1 -3
- data/ataru_setup.rb +72 -0
- data/find_missing_tests.rb +34 -0
- data/lib/yaks.rb +8 -10
- data/lib/yaks/breaking_changes.rb +4 -6
- data/lib/yaks/builder.rb +1 -1
- data/lib/yaks/changelog.rb +1 -1
- data/lib/yaks/collection_mapper.rb +8 -5
- data/lib/yaks/collection_resource.rb +0 -1
- data/lib/yaks/config.rb +17 -7
- data/lib/yaks/configurable.rb +20 -14
- data/lib/yaks/default_policy.rb +82 -33
- data/lib/yaks/format.rb +7 -3
- data/lib/yaks/format/collection_json.rb +4 -4
- data/lib/yaks/format/hal.rb +1 -2
- data/lib/yaks/format/halo.rb +2 -4
- data/lib/yaks/format/json_api.rb +46 -27
- data/lib/yaks/html5_forms.rb +0 -2
- data/lib/yaks/mapper.rb +5 -5
- data/lib/yaks/mapper/association.rb +7 -7
- data/lib/yaks/mapper/association_mapper.rb +2 -0
- data/lib/yaks/mapper/attribute.rb +10 -4
- data/lib/yaks/mapper/config.rb +2 -2
- data/lib/yaks/mapper/form.rb +4 -10
- data/lib/yaks/mapper/form/config.rb +16 -17
- data/lib/yaks/mapper/form/dynamic_field.rb +1 -1
- data/lib/yaks/mapper/form/field.rb +16 -7
- data/lib/yaks/mapper/form/field/option.rb +5 -4
- data/lib/yaks/mapper/form/fieldset.rb +1 -1
- data/lib/yaks/mapper/form/legend.rb +18 -0
- data/lib/yaks/mapper/has_many.rb +1 -0
- data/lib/yaks/mapper/link.rb +7 -4
- data/lib/yaks/null_resource.rb +4 -5
- data/lib/yaks/pipeline.rb +2 -2
- data/lib/yaks/primitivize.rb +3 -2
- data/lib/yaks/reader/hal.rb +12 -13
- data/lib/yaks/reader/json_api.rb +50 -33
- data/lib/yaks/resource.rb +6 -7
- data/lib/yaks/resource/form.rb +2 -12
- data/lib/yaks/resource/form/field.rb +4 -3
- data/lib/yaks/resource/form/field/option.rb +1 -1
- data/lib/yaks/resource/form/fieldset.rb +1 -1
- data/lib/yaks/resource/form/legend.rb +18 -0
- data/lib/yaks/resource/has_fields.rb +13 -7
- data/lib/yaks/resource/link.rb +1 -1
- data/lib/yaks/runner.rb +5 -2
- data/lib/yaks/serializer.rb +2 -3
- data/lib/yaks/util.rb +7 -8
- data/lib/yaks/version.rb +1 -1
- data/spec/acceptance/acceptance_spec.rb +53 -38
- data/spec/acceptance/json_shared_examples.rb +45 -12
- data/spec/acceptance/models.rb +1 -1
- data/spec/integration/dynamic_form_fields_spec.rb +0 -1
- data/spec/integration/fieldset_spec.rb +18 -20
- data/spec/integration/map_to_resource_spec.rb +6 -6
- data/spec/json/{confucius.collection.json → confucius.collection_json.json} +0 -0
- data/spec/json/confucius.json_api.json +43 -27
- data/spec/json/list_of_quotes.collection_json.json +43 -0
- data/spec/json/list_of_quotes.hal.json +18 -0
- data/spec/json/list_of_quotes.json_api.json +25 -0
- data/spec/json/youtypeitwepostit.collection_json.json +45 -0
- data/spec/spec_helper.rb +4 -3
- data/spec/support/classes_for_policy_testing.rb +38 -14
- data/spec/support/deep_eql.rb +21 -18
- data/spec/support/pet_mapper.rb +2 -0
- data/spec/support/shared_contexts.rb +9 -9
- data/spec/unit/yaks/builder_spec.rb +41 -18
- data/spec/unit/yaks/collection_mapper_spec.rb +22 -19
- data/spec/unit/yaks/collection_resource_spec.rb +16 -8
- data/spec/unit/yaks/config_spec.rb +215 -19
- data/spec/unit/yaks/configurable_spec.rb +66 -7
- data/spec/unit/yaks/default_policy/derive_mapper_from_collection_spec.rb +47 -0
- data/spec/unit/yaks/default_policy/derive_mapper_from_item_spec.rb +114 -0
- data/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +29 -71
- data/spec/unit/yaks/default_policy_spec.rb +4 -5
- data/spec/unit/yaks/format/collection_json_spec.rb +35 -36
- data/spec/unit/yaks/format/hal_spec.rb +3 -3
- data/spec/unit/yaks/format/json_api_spec.rb +109 -68
- data/spec/unit/yaks/format_spec.rb +34 -0
- data/spec/unit/yaks/fp/callable_spec.rb +5 -3
- data/spec/unit/yaks/mapper/association_mapper_spec.rb +22 -4
- data/spec/unit/yaks/mapper/association_spec.rb +23 -11
- data/spec/unit/yaks/mapper/attribute_spec.rb +46 -7
- data/spec/unit/yaks/mapper/config_spec.rb +2 -3
- data/spec/unit/yaks/mapper/form/config_spec.rb +95 -0
- data/spec/unit/yaks/mapper/form/dynamic_field_spec.rb +30 -0
- data/spec/unit/yaks/mapper/form/field/option_spec.rb +48 -4
- data/spec/unit/yaks/mapper/form/field_spec.rb +43 -2
- data/spec/unit/yaks/mapper/form/fieldset_spec.rb +67 -8
- data/spec/unit/yaks/mapper/form/legend_spec.rb +52 -0
- data/spec/unit/yaks/mapper/form_spec.rb +84 -23
- data/spec/unit/yaks/mapper/has_many_spec.rb +39 -36
- data/spec/unit/yaks/mapper/has_one_spec.rb +28 -20
- data/spec/unit/yaks/mapper/link_spec.rb +68 -16
- data/spec/unit/yaks/mapper_spec.rb +118 -30
- data/spec/unit/yaks/null_resource_spec.rb +83 -52
- data/spec/unit/yaks/pipeline_spec.rb +101 -74
- data/spec/unit/yaks/primitivize_spec.rb +25 -6
- data/spec/unit/yaks/resource/form/field_spec.rb +5 -5
- data/spec/unit/yaks/resource/form/fieldset_spec.rb +7 -0
- data/spec/unit/yaks/resource/form/legend_spec.rb +8 -0
- data/spec/unit/yaks/resource/form_spec.rb +17 -37
- data/spec/unit/yaks/resource/has_fields_spec.rb +44 -3
- data/spec/unit/yaks/resource/link_spec.rb +11 -6
- data/spec/unit/yaks/resource_spec.rb +87 -98
- data/spec/unit/yaks/runner_spec.rb +112 -28
- data/spec/unit/yaks/serializer_spec.rb +1 -1
- data/spec/unit/yaks/util_spec.rb +30 -10
- data/spec/yaml/list_of_quotes.yaml +13 -0
- data/yaks.gemspec +21 -13
- metadata +129 -41
- data/lib/yaks/attributes.rb +0 -86
- data/lib/yaks/fp.rb +0 -26
- data/lib/yaks/identifier/link_relation.rb +0 -17
- data/resources/iana-link-relations.csv +0 -152
- data/spec/json/youtypeitwepostit.collection.json +0 -45
- data/spec/unit/yaks/attributes_spec.rb +0 -178
- data/spec/unit/yaks/fp_spec.rb +0 -29
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mutant'
|
4
|
+
require 'pry'
|
5
|
+
|
6
|
+
# These are private methods that are tested by other methods in the same class
|
7
|
+
SKIP = %w[
|
8
|
+
Yaks::CollectionMapper#collection_rel
|
9
|
+
Yaks::CollectionMapper#collection_type
|
10
|
+
Yaks::CollectionMapper#mapper_for_model
|
11
|
+
Yaks::Resource::Form::Field#select_options_for_value
|
12
|
+
Yaks::Mapper::AssociationMapper#add_link
|
13
|
+
Yaks::Mapper::AssociationMapper#add_subresource
|
14
|
+
Yaks::Mapper::Link#resource_link_options
|
15
|
+
]
|
16
|
+
|
17
|
+
args = ["-Ilib", "-ryaks", "--use", "rspec", "Yaks*"]
|
18
|
+
env = Mutant::Env::Bootstrap.call(Mutant::CLI.call(args))
|
19
|
+
|
20
|
+
integration = env.config.integration
|
21
|
+
|
22
|
+
integration.setup
|
23
|
+
binding.pry if integration.all_tests.empty? # rubocop:disable Lint/Debugger
|
24
|
+
|
25
|
+
env.subjects.each do |subject|
|
26
|
+
match_expression = subject.match_expressions.first
|
27
|
+
subject_tests = integration.all_tests.select do |test|
|
28
|
+
match_expression.prefix?(test.expression)
|
29
|
+
end
|
30
|
+
unless subject_tests.any? || SKIP.include?(subject.expression.syntax)
|
31
|
+
puts subject.identification
|
32
|
+
exit if ARGV.include?("-1")
|
33
|
+
end
|
34
|
+
end
|
data/lib/yaks.rb
CHANGED
@@ -4,17 +4,15 @@ require 'pathname'
|
|
4
4
|
require 'json'
|
5
5
|
require 'csv'
|
6
6
|
|
7
|
-
require 'anima'
|
8
7
|
require 'concord'
|
8
|
+
require 'attribs'
|
9
9
|
require 'inflection'
|
10
10
|
require 'uri_template'
|
11
11
|
require 'rack/accept'
|
12
12
|
|
13
13
|
require 'yaks/version'
|
14
14
|
require 'yaks/util'
|
15
|
-
require 'yaks/attributes'
|
16
15
|
require 'yaks/configurable'
|
17
|
-
require 'yaks/fp'
|
18
16
|
require 'yaks/fp/callable'
|
19
17
|
require 'yaks/primitivize'
|
20
18
|
require 'yaks/builder'
|
@@ -24,7 +22,6 @@ require 'yaks/default_policy'
|
|
24
22
|
require 'yaks/serializer'
|
25
23
|
require 'yaks/config'
|
26
24
|
|
27
|
-
|
28
25
|
module Yaks
|
29
26
|
Undefined = Module.new.freeze
|
30
27
|
|
@@ -34,6 +31,7 @@ module Yaks
|
|
34
31
|
DSL_METHODS = [
|
35
32
|
:format_options,
|
36
33
|
:rel_template,
|
34
|
+
:mapper_for,
|
37
35
|
:before,
|
38
36
|
:after,
|
39
37
|
:around,
|
@@ -42,13 +40,13 @@ module Yaks
|
|
42
40
|
:mapper_namespace,
|
43
41
|
:serializer,
|
44
42
|
:json_serializer,
|
45
|
-
:map_to_primitive
|
43
|
+
:map_to_primitive
|
46
44
|
]
|
47
45
|
|
48
46
|
ConfigBuilder = Builder.new(Yaks::Config) do
|
49
|
-
def_set
|
50
|
-
def_forward
|
51
|
-
def_forward
|
47
|
+
def_set(*Yaks::Config.attributes.names)
|
48
|
+
def_forward(*DSL_METHODS)
|
49
|
+
def_forward(*Yaks::DefaultPolicy.public_instance_methods(false))
|
52
50
|
end
|
53
51
|
|
54
52
|
class << self
|
@@ -61,14 +59,12 @@ module Yaks
|
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
64
|
-
|
65
62
|
require 'yaks/resource'
|
66
63
|
require 'yaks/null_resource'
|
67
64
|
require 'yaks/resource/link'
|
68
65
|
require 'yaks/collection_resource'
|
69
66
|
|
70
67
|
require 'yaks/html5_forms'
|
71
|
-
require 'yaks/identifier/link_relation'
|
72
68
|
|
73
69
|
require 'yaks/mapper/association'
|
74
70
|
require 'yaks/mapper/has_one'
|
@@ -78,6 +74,7 @@ require 'yaks/mapper/link'
|
|
78
74
|
require 'yaks/mapper/form/field/option'
|
79
75
|
require 'yaks/mapper/form/field'
|
80
76
|
require 'yaks/mapper/form/fieldset'
|
77
|
+
require 'yaks/mapper/form/legend'
|
81
78
|
require 'yaks/mapper/form/dynamic_field'
|
82
79
|
require 'yaks/mapper/form/config'
|
83
80
|
require 'yaks/mapper/form'
|
@@ -91,6 +88,7 @@ require 'yaks/resource/form'
|
|
91
88
|
require 'yaks/resource/form/field'
|
92
89
|
require 'yaks/resource/form/field/option'
|
93
90
|
require 'yaks/resource/form/fieldset'
|
91
|
+
require 'yaks/resource/form/legend'
|
94
92
|
|
95
93
|
require 'yaks/format'
|
96
94
|
require 'yaks/format/hal'
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module Yaks
|
2
|
-
|
3
2
|
# These are displayed in a post-install message when installing the
|
4
3
|
# gem to aid upgraiding
|
5
4
|
|
6
5
|
BreakingChanges = {
|
7
6
|
|
8
|
-
|
7
|
+
'0.7.6' => %q~
|
9
8
|
Breaking Changes in Yaks 0.7.6
|
10
9
|
==============================
|
11
10
|
Breaking change: using a symbol instead of link template no longer
|
@@ -27,7 +26,7 @@ with the attribute name in HTML. An alias is available but will output
|
|
27
26
|
a deprecation warning.
|
28
27
|
~,
|
29
28
|
|
30
|
-
|
29
|
+
'0.7.0' => %q~
|
31
30
|
Breaking Changes in Yaks 0.7.0
|
32
31
|
==============================
|
33
32
|
Yaks::Resource#subresources is now an array, not a hash. The rel is
|
@@ -40,7 +39,7 @@ have custom implementations of any of these, or hooks that are not
|
|
40
39
|
specified as ruby blocks, you will need to take this into account
|
41
40
|
~,
|
42
41
|
|
43
|
-
|
42
|
+
'0.5.0' => %q~
|
44
43
|
|
45
44
|
Breaking Changes in Yaks 0.5.0
|
46
45
|
==============================
|
@@ -61,7 +60,7 @@ for full documentation.
|
|
61
60
|
|
62
61
|
~,
|
63
62
|
|
64
|
-
|
63
|
+
'0.4.3' => %q~
|
65
64
|
|
66
65
|
Breaking Changes in Yaks 0.4.3
|
67
66
|
==============================
|
@@ -81,5 +80,4 @@ documentation.
|
|
81
80
|
|
82
81
|
BreakingChanges['0.4.4'] = BreakingChanges['0.4.3']
|
83
82
|
BreakingChanges['0.7.1'] = BreakingChanges['0.7.0']
|
84
|
-
|
85
83
|
end
|
data/lib/yaks/builder.rb
CHANGED
data/lib/yaks/changelog.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Yaks
|
2
2
|
class CollectionMapper < Mapper
|
3
|
-
|
3
|
+
alias_method :collection, :object
|
4
4
|
|
5
5
|
# @param [Array] collection
|
6
6
|
# @return [Array]
|
@@ -14,9 +14,12 @@ module Yaks
|
|
14
14
|
end
|
15
15
|
}
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
# For collections from associations the rel will be based on the
|
18
|
+
# association. At the top level there's no association, so we
|
19
|
+
# use a generic rel. This matters especially for HAL, where a
|
20
|
+
# top-level collection is rendered as an object with the
|
21
|
+
# collection as a subresource.
|
22
|
+
attrs[:rels] = [collection_rel] if context[:mapper_stack].empty?
|
20
23
|
|
21
24
|
map_attributes(
|
22
25
|
map_links(
|
@@ -29,7 +32,7 @@ module Yaks
|
|
29
32
|
|
30
33
|
def collection_rel
|
31
34
|
if collection_type
|
32
|
-
policy.expand_rel(
|
35
|
+
policy.expand_rel(pluralize(collection_type))
|
33
36
|
else
|
34
37
|
'collection'
|
35
38
|
end
|
data/lib/yaks/config.rb
CHANGED
@@ -2,7 +2,7 @@ module Yaks
|
|
2
2
|
class Config
|
3
3
|
extend Yaks::Util::Deprecated
|
4
4
|
include Yaks::FP::Callable,
|
5
|
-
|
5
|
+
Attribs.new(
|
6
6
|
format_options_hash: Hash.new({}),
|
7
7
|
default_format: :hal,
|
8
8
|
policy_options: {},
|
@@ -13,12 +13,12 @@ module Yaks
|
|
13
13
|
)
|
14
14
|
|
15
15
|
class << self
|
16
|
-
|
16
|
+
alias_method :create, :new
|
17
17
|
end
|
18
18
|
|
19
19
|
deprecated_alias :namespace, :mapper_namespace
|
20
20
|
|
21
|
-
def format_options(format, options
|
21
|
+
def format_options(format, options)
|
22
22
|
with(format_options_hash: format_options_hash.merge(format => options))
|
23
23
|
end
|
24
24
|
|
@@ -27,7 +27,7 @@ module Yaks
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def json_serializer(&serializer)
|
30
|
-
|
30
|
+
serializer(:json, &serializer)
|
31
31
|
end
|
32
32
|
|
33
33
|
%w[before after around skip].map(&:intern).each do |hook_type|
|
@@ -37,11 +37,17 @@ module Yaks
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def rel_template(template)
|
40
|
-
with(policy_options: policy_options.merge(:
|
40
|
+
with(policy_options: policy_options.merge(rel_template: template))
|
41
41
|
end
|
42
42
|
|
43
43
|
def mapper_namespace(namespace)
|
44
|
-
with(policy_options: policy_options.merge(:
|
44
|
+
with(policy_options: policy_options.merge(namespace: namespace))
|
45
|
+
end
|
46
|
+
|
47
|
+
def mapper_for(rule, mapper_class)
|
48
|
+
policy_options[:mapper_rules] ||= {}
|
49
|
+
mapper_rules = policy_options[:mapper_rules].merge(rule => mapper_class)
|
50
|
+
with(policy_options: policy_options.merge(mapper_rules: mapper_rules))
|
45
51
|
end
|
46
52
|
|
47
53
|
def map_to_primitive(*args, &block)
|
@@ -80,12 +86,16 @@ module Yaks
|
|
80
86
|
def call(object, options = {})
|
81
87
|
runner(object, options).call
|
82
88
|
end
|
83
|
-
|
89
|
+
alias_method :serialize, :call
|
84
90
|
|
85
91
|
def map(object, options = {})
|
86
92
|
runner(object, options).map
|
87
93
|
end
|
88
94
|
|
95
|
+
def format(data, options = {})
|
96
|
+
runner(data, options).format
|
97
|
+
end
|
98
|
+
|
89
99
|
def read(data, options = {})
|
90
100
|
runner(data, options).read
|
91
101
|
end
|
data/lib/yaks/configurable.rb
CHANGED
@@ -34,12 +34,16 @@ module Yaks
|
|
34
34
|
def def_set(*method_names)
|
35
35
|
method_names.each do |method_name|
|
36
36
|
define_singleton_method method_name do |arg = Undefined, &block|
|
37
|
-
if arg
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
if arg.equal?(Undefined)
|
38
|
+
unless block
|
39
|
+
raise ArgumentError, "setting #{method_name}: no value and no block given"
|
40
|
+
end
|
41
|
+
self.config = config.with(method_name => block)
|
41
42
|
else
|
42
|
-
|
43
|
+
if block
|
44
|
+
raise ArgumentError, "ambiguous invocation setting #{method_name}: give either a value or a block, not both."
|
45
|
+
end
|
46
|
+
self.config = config.with(method_name => arg)
|
43
47
|
end
|
44
48
|
end
|
45
49
|
end
|
@@ -50,15 +54,15 @@ module Yaks
|
|
50
54
|
#
|
51
55
|
# Either takes a list of methods to forward, or a mapping (hash)
|
52
56
|
# of source to destination method name.
|
53
|
-
def def_forward(
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
define_singleton_method method_name do |*args, &block|
|
60
|
-
self.config = config.public_send(target, *args, &block)
|
57
|
+
def def_forward(mappings, *names)
|
58
|
+
if mappings.instance_of? Hash
|
59
|
+
mappings.each do |method_name, target|
|
60
|
+
define_singleton_method method_name do |*args, &block|
|
61
|
+
self.config = config.public_send(target, *args, &block)
|
62
|
+
end
|
61
63
|
end
|
64
|
+
else
|
65
|
+
def_forward([mappings, *names].map{|name| {name => name}}.inject(:merge))
|
62
66
|
end
|
63
67
|
end
|
64
68
|
|
@@ -70,6 +74,7 @@ module Yaks
|
|
70
74
|
# This will generate a `fieldset` method, which will call
|
71
75
|
# `Fieldset.create`, and append the result to `config.fields`
|
72
76
|
def def_add(name, options)
|
77
|
+
old_verbose, $VERBOSE = $VERBOSE, false # skip method redefinition warning
|
73
78
|
define_singleton_method name do |*args, &block|
|
74
79
|
defaults = options.fetch(:defaults, {})
|
75
80
|
klass = options.fetch(:create)
|
@@ -85,7 +90,8 @@ module Yaks
|
|
85
90
|
klass.create(*args, &block)
|
86
91
|
)
|
87
92
|
end
|
93
|
+
ensure
|
94
|
+
$VERBOSE = old_verbose
|
88
95
|
end
|
89
|
-
|
90
96
|
end
|
91
97
|
end
|
data/lib/yaks/default_policy.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
module Yaks
|
2
3
|
class DefaultPolicy
|
3
4
|
include Util
|
@@ -5,7 +6,8 @@ module Yaks
|
|
5
6
|
# Default policy options.
|
6
7
|
DEFAULTS = {
|
7
8
|
rel_template: "rel:{rel}",
|
8
|
-
namespace:
|
9
|
+
namespace: Object,
|
10
|
+
mapper_rules: {}
|
9
11
|
}
|
10
12
|
|
11
13
|
# @!attribute [r]
|
@@ -17,36 +19,57 @@ module Yaks
|
|
17
19
|
@options = DEFAULTS.merge(options)
|
18
20
|
end
|
19
21
|
|
22
|
+
# Main point of entry for mapper derivation. Calls
|
23
|
+
# derive_mapper_from_collection or derive_mapper_from_item
|
24
|
+
# depending on the model.
|
25
|
+
#
|
20
26
|
# @param model [Object]
|
21
27
|
# @return [Class] A mapper, typically a subclass of Yaks::Mapper
|
22
28
|
#
|
23
|
-
# @raise [
|
29
|
+
# @raise [RuntimeError] occurs when no mapper is found
|
24
30
|
def derive_mapper_from_object(model)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
CollectionMapper
|
38
|
-
else
|
39
|
-
klass = model.class
|
31
|
+
mapper = detect_configured_mapper_for(model)
|
32
|
+
return mapper if mapper
|
33
|
+
return derive_mapper_from_collection(model) if model.respond_to? :to_ary
|
34
|
+
derive_mapper_from_item(model)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Derives a mapper from the given collection.
|
38
|
+
#
|
39
|
+
# @param collection [Object]
|
40
|
+
# @return [Class] A mapper, typically a subclass of Yaks::Mapper
|
41
|
+
def derive_mapper_from_collection(collection)
|
42
|
+
if m = collection.first
|
43
|
+
name = "#{m.class.name.split('::').last}CollectionMapper"
|
40
44
|
begin
|
41
|
-
|
42
|
-
|
43
|
-
rescue NameError
|
44
|
-
klass = klass.superclass
|
45
|
-
retry if klass
|
45
|
+
return @options[:namespace].const_get(name)
|
46
|
+
rescue NameError # rubocop:disable Lint/HandleExceptions
|
46
47
|
end
|
47
|
-
name = model.class.name.split('::').last
|
48
|
-
raise "Failed to find a mapper for #{model.inspect}. Did you mean to implement #{name}Mapper?"
|
49
48
|
end
|
49
|
+
begin
|
50
|
+
return @options[:namespace].const_get(:CollectionMapper)
|
51
|
+
rescue NameError # rubocop:disable Lint/HandleExceptions
|
52
|
+
end
|
53
|
+
CollectionMapper
|
54
|
+
end
|
55
|
+
|
56
|
+
# Derives a mapper from the given item. This item should not
|
57
|
+
# be a collection.
|
58
|
+
#
|
59
|
+
# @param item [Object]
|
60
|
+
# @return [Class] A mapper, typically a subclass of Yaks::Mapper
|
61
|
+
#
|
62
|
+
# @raise [RuntimeError] only occurs when no mapper is found for the given item.
|
63
|
+
def derive_mapper_from_item(item)
|
64
|
+
klass = item.class
|
65
|
+
namespaces = klass.name.split("::")[0...-1]
|
66
|
+
begin
|
67
|
+
return build_mapper_class(namespaces, klass)
|
68
|
+
rescue NameError
|
69
|
+
klass = next_class_for_lookup(item, namespaces, klass)
|
70
|
+
retry if klass
|
71
|
+
end
|
72
|
+
raise_mapper_not_found(item)
|
50
73
|
end
|
51
74
|
|
52
75
|
# Derive the a mapper type name
|
@@ -63,9 +86,9 @@ module Yaks
|
|
63
86
|
|
64
87
|
# Derive the mapper type name from a collection
|
65
88
|
#
|
66
|
-
# This inspects the first element of the collection, so
|
67
|
-
# requires a
|
68
|
-
# collection
|
89
|
+
# This inspects the first element of the collection, so
|
90
|
+
# it requires a collection with truthy elements. Will
|
91
|
+
# return `nil` if the collection has no truthy elements.
|
69
92
|
#
|
70
93
|
# @param [#first] collection
|
71
94
|
#
|
@@ -73,11 +96,8 @@ module Yaks
|
|
73
96
|
#
|
74
97
|
# @raise [NameError]
|
75
98
|
def derive_type_from_collection(collection)
|
76
|
-
if collection.
|
77
|
-
|
78
|
-
derive_mapper_from_object(collection.first)
|
79
|
-
)
|
80
|
-
end
|
99
|
+
return if collection.none?
|
100
|
+
derive_type_from_mapper_class(derive_mapper_from_object(collection.first))
|
81
101
|
end
|
82
102
|
|
83
103
|
def derive_mapper_from_association(association)
|
@@ -87,7 +107,7 @@ module Yaks
|
|
87
107
|
# @param association [Yaks::Mapper::Association]
|
88
108
|
# @return [String]
|
89
109
|
def derive_rel_from_association(association)
|
90
|
-
expand_rel(
|
110
|
+
expand_rel(association.name)
|
91
111
|
end
|
92
112
|
|
93
113
|
# @param relname [String]
|
@@ -96,5 +116,34 @@ module Yaks
|
|
96
116
|
URITemplate.new(@options[:rel_template]).expand(rel: relname)
|
97
117
|
end
|
98
118
|
|
119
|
+
private
|
120
|
+
|
121
|
+
def build_mapper_class(namespaces, klass)
|
122
|
+
mapper_class = "#{klass.name.split('::').last}Mapper"
|
123
|
+
[*namespaces, mapper_class].inject(@options[:namespace]) do |namespace, module_or_class|
|
124
|
+
namespace.const_get(module_or_class, false)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def next_class_for_lookup(item, namespaces, klass)
|
129
|
+
superclass = klass.superclass
|
130
|
+
return superclass if superclass < Object
|
131
|
+
return nil if namespaces.empty?
|
132
|
+
namespaces.clear
|
133
|
+
item.class
|
134
|
+
end
|
135
|
+
|
136
|
+
def raise_mapper_not_found(item)
|
137
|
+
namespace = "#{@options[:namespace]}::" unless Object.equal?(@options[:namespace])
|
138
|
+
mapper_class = "#{namespace}#{item.class}Mapper"
|
139
|
+
raise "Failed to find a mapper for #{item.inspect}. Did you mean to implement #{mapper_class}?"
|
140
|
+
end
|
141
|
+
|
142
|
+
def detect_configured_mapper_for(object)
|
143
|
+
@options[:mapper_rules].each do |rule, mapper_class|
|
144
|
+
return mapper_class if rule === object # rubocop:disable Style/CaseEquality
|
145
|
+
end
|
146
|
+
nil
|
147
|
+
end
|
99
148
|
end
|
100
149
|
end
|