yaks 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +65 -5
  4. data/README.md +38 -8
  5. data/Rakefile +33 -0
  6. data/lib/yaks/breaking_changes.rb +22 -0
  7. data/lib/yaks/collection_mapper.rb +18 -21
  8. data/lib/yaks/collection_resource.rb +19 -5
  9. data/lib/yaks/config/dsl.rb +78 -0
  10. data/lib/yaks/config.rb +37 -63
  11. data/lib/yaks/default_policy.rb +27 -9
  12. data/lib/yaks/{serializer → format}/collection_json.rb +7 -3
  13. data/lib/yaks/{serializer → format}/hal.rb +14 -4
  14. data/lib/yaks/{serializer → format}/json_api.rb +22 -4
  15. data/lib/yaks/{serializer.rb → format.rb} +5 -5
  16. data/lib/yaks/fp/hash_updatable.rb +17 -0
  17. data/lib/yaks/fp/updatable.rb +15 -0
  18. data/lib/yaks/mapper/association.rb +24 -21
  19. data/lib/yaks/mapper/association_mapper.rb +42 -0
  20. data/lib/yaks/mapper/attribute.rb +17 -0
  21. data/lib/yaks/mapper/class_methods.rb +0 -1
  22. data/lib/yaks/mapper/config.rb +8 -28
  23. data/lib/yaks/mapper/has_many.rb +8 -3
  24. data/lib/yaks/mapper/has_one.rb +1 -1
  25. data/lib/yaks/mapper/link.rb +13 -13
  26. data/lib/yaks/mapper.rb +28 -32
  27. data/lib/yaks/null_resource.rb +1 -0
  28. data/lib/yaks/resource.rb +15 -5
  29. data/lib/yaks/version.rb +1 -1
  30. data/lib/yaks.rb +16 -10
  31. data/spec/acceptance/acceptance_spec.rb +16 -17
  32. data/spec/acceptance/json_shared_examples.rb +8 -0
  33. data/spec/acceptance/models.rb +2 -2
  34. data/spec/integration/map_to_resource_spec.rb +3 -3
  35. data/spec/json/confucius.collection.json +39 -0
  36. data/spec/json/confucius.hal.json +7 -4
  37. data/spec/json/confucius.json_api.json +1 -1
  38. data/spec/spec_helper.rb +6 -0
  39. data/spec/support/classes_for_policy_testing.rb +36 -0
  40. data/spec/support/shared_contexts.rb +1 -1
  41. data/spec/unit/yaks/collection_mapper_spec.rb +34 -9
  42. data/spec/unit/yaks/collection_resource_spec.rb +4 -4
  43. data/spec/unit/yaks/config/dsl_spec.rb +91 -0
  44. data/spec/unit/yaks/config_spec.rb +10 -6
  45. data/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +80 -0
  46. data/spec/unit/yaks/default_policy_spec.rb +50 -0
  47. data/spec/unit/yaks/{serializer → format}/hal_spec.rb +1 -1
  48. data/spec/unit/yaks/format/json_api_spec.rb +42 -0
  49. data/spec/unit/yaks/format_spec.rb +12 -0
  50. data/spec/unit/yaks/fp/hash_updatable_spec.rb +22 -0
  51. data/spec/unit/yaks/fp/updatable_spec.rb +22 -0
  52. data/spec/unit/yaks/mapper/association_mapper_spec.rb +60 -0
  53. data/spec/unit/yaks/mapper/association_spec.rb +96 -41
  54. data/spec/unit/yaks/mapper/attribute_spec.rb +20 -0
  55. data/spec/unit/yaks/mapper/class_methods_spec.rb +49 -10
  56. data/spec/unit/yaks/mapper/config_spec.rb +25 -50
  57. data/spec/unit/yaks/mapper/has_many_spec.rb +33 -5
  58. data/spec/unit/yaks/mapper/has_one_spec.rb +32 -17
  59. data/spec/unit/yaks/mapper/link_spec.rb +44 -12
  60. data/spec/unit/yaks/mapper_spec.rb +45 -17
  61. data/spec/unit/yaks/resource_spec.rb +41 -7
  62. data/yaks.gemspec +7 -1
  63. metadata +72 -21
  64. data/examples/hal01.rb +0 -126
  65. data/examples/jsonapi01.rb +0 -68
  66. data/examples/jsonapi02.rb +0 -62
  67. data/examples/jsonapi03.rb +0 -86
  68. data/spec/support/serializers.rb +0 -14
  69. data/spec/unit/yaks/serializer_spec.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b888259337e9fa643458e613fda2f50e561a72e
4
- data.tar.gz: e6ff86a9a5d402b857041f1a676b81f6324078d7
3
+ metadata.gz: f8ee4f04ef31bd3c1e944ee723c910bf37dd97b8
4
+ data.tar.gz: 93282ee4d7a30bdb826ccc81447d86db1de245f0
5
5
  SHA512:
6
- metadata.gz: edfa665288d44ed62d397beeb2419092b7220129475c77f5cbce4413a981f1d57f44578faf27e3a77da3c6a818a3b5bc0f5bbeaeaa966aeab82d55f6b1960694
7
- data.tar.gz: 7391bc4fab6497ce52c6353db032786df91ab01730cd8486aed53179321ebd3c9baf49a54509edbcddd14796b1daefecc98903b0bfd8b9fe94753cb4fe2f1490
6
+ metadata.gz: d09019c49799077e500badde0c259fa41d06f2fdbfe3ec3c7c7cf71625ce786d2eb682b2b449edc8a683b8a24a20234cd3ea16716697154a58fcd88c6a6773a9
7
+ data.tar.gz: b0107900f0d00a2b30ab7d6cd701b84a59e3155961a653847b863d5cc0a569c0ff24640769b78826afad31fa6b5667cf3cf294961de82f3b1c6fbd8301f8c460
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ pkg
2
2
  .bundle
3
3
  coverage
4
4
  Gemfile.lock
5
+ *~
data/CHANGELOG.md CHANGED
@@ -1,6 +1,66 @@
1
1
  ### Development
2
2
  [full changelog](http://github.com/plexus/yaks/compare/v0.4.2...master)
3
3
 
4
+ * when specifying a rel_template, instead of allowing for {src} and {dest} fields, now a single {rel} field is expected, which corresponds more with typical usage.
5
+
6
+ ```ruby
7
+ Yaks.new do
8
+ rel_template 'http://my-api/docs/relationships/{rel}'
9
+ end
10
+ ```
11
+
12
+ * Yaks::Serializer has been renamed to Yaks::Format
13
+
14
+ * Yaks::Mapper#{map_attributes,map_links,map_subresource} signature has changed, they now are responsible for adding themselves to a resource instance.
15
+
16
+ ```ruby
17
+ class FooMapper < Yaks::Mapper
18
+ def map_attributes(resource)
19
+ resource.update_attributes(:example => 'attribute')
20
+ end
21
+ end
22
+ ```
23
+
24
+ * Conditionally turn associations into links
25
+
26
+ ```ruby
27
+ class ShowMapper < Yaks::Mapper
28
+ has_many :events, href: '/show/{id}/events', link_if: ->{ events.count > 50 }
29
+ end
30
+ ```
31
+
32
+ * Reify `Yaks::Mapper::Attribute`
33
+
34
+ * Remove `Yaks::Mapper#filter`, instead override `#attributes` or `#associations` to filter things out, for example:
35
+
36
+ ```ruby
37
+ class SongMapper
38
+ attributes :title, :duration, :lyrics
39
+ has_one :artist
40
+ has_one :album
41
+
42
+ def minimal?
43
+ env['HTTP_PREFER'] =~ /minimal/
44
+ end
45
+
46
+ def attributes
47
+ if minimal?
48
+ super.reject {|attr| attr.name.equal? :lyrics } # These are instances of Yaks::Mapper::Attribute
49
+ else
50
+ super
51
+ end
52
+ end
53
+
54
+ def associations
55
+ return [] if minimal?
56
+ super
57
+ end
58
+ end
59
+ ```
60
+
61
+ * Give Attribute, Link, Association a common interface : `add_to_resource(resource, mapper, context)`
62
+ * Add persistent update methods to `Yaks::Resource`
63
+
4
64
  ### v0.4.2
5
65
 
6
66
  * JSON-API: render self links as href attributes
@@ -10,13 +70,13 @@
10
70
  * Make Yaks::CollectionMapper#collection overridable for pagination
11
71
  * Don't render links from custom link methods (link :foo, :method_that_generates_url) that return nil
12
72
 
13
- # v0.4.1
73
+ ### v0.4.1
14
74
 
15
75
  * Change how env is passed to yaks.serialize to match docs
16
76
  * Fix JSON-API bug (#18 reported by Nicolas Blanco)
17
77
  * Don't pluralize has_one association names in JSON-API
18
78
 
19
- # v0.4.0
79
+ ## v0.4.0
20
80
 
21
81
  * Introduce after {} post-processing hook
22
82
  * Streamline interfaces and variable names, especially the use of `call`
@@ -25,7 +85,7 @@
25
85
  * Switch back to using `src` and `dest` as the rel-template keys, instead of `association_name`
26
86
  * deprecate `mapper_namespace` in favor of `namespace`
27
87
 
28
- # v0.4.0.rc1
88
+ ### v0.4.0.rc1
29
89
 
30
90
  * Introduce Yaks.new as the main public interface
31
91
  * Fix JsonApiSerializer and make it compliant with current spec
@@ -36,10 +96,10 @@
36
96
  * Honor the HTTP Accept header if it is present in the rack env
37
97
  * Add map_to_primitive configuration option
38
98
 
39
- # v0.3.0
99
+ ## v0.3.0
40
100
 
41
101
  * Allow partial expansion of templates, expand certain fields, leave others as URI template in the result.
42
102
 
43
- # v0.2.0
103
+ ## v0.2.0
44
104
 
45
105
  * links can now take a simple for a template to compute a link just like an attribute
data/README.md CHANGED
@@ -62,7 +62,7 @@ or a bit more elaborate
62
62
  ```ruby
63
63
  yaks = Yaks.new do
64
64
  default_format :json_api
65
- rel_template 'http://api.example.com/rels/{dest}'
65
+ rel_template 'http://api.example.com/rels/{rel}'
66
66
  format_options(:hal, plural_links: [:copyright])
67
67
  end
68
68
 
@@ -100,11 +100,30 @@ end
100
100
 
101
101
  #### Filtering
102
102
 
103
- Implement `filter(attrs)` to filter out specific attributes, e.g. based on options.
103
+ Implementing a `#filter` method in your mappers is no longer supported. Instead you can override `#attributes`, or `#associations`.
104
104
 
105
105
  ```ruby
106
- def filter(attrs)
107
- attrs.reject{|attr| options[:exclude].include? attr }
106
+ class SongMapper
107
+ attributes :title, :duration, :lyrics
108
+
109
+ has_one :artist
110
+ has_one :album
111
+
112
+ def minimal?
113
+ env['HTTP_PREFER'] =~ /minimal/
114
+ end
115
+
116
+ # @return Array<Yaks::Mapper::Attribute>
117
+ def attributes
118
+ return super.reject {|attr| attr.name.equal? :lyrics } if minimal?
119
+ super
120
+ end
121
+
122
+ # @return Array<Yaks::Mapper::Association>
123
+ def associations
124
+ return [] if minimal?
125
+ super
126
+ end
108
127
  end
109
128
  ```
110
129
 
@@ -159,6 +178,13 @@ Options
159
178
  * `:mapper` : Use a specific for each instance, will be derived from the class name if omitted (see Policy vs Configuration)
160
179
  * `:collection_mapper` : For mapping the collection as a whole, this defaults to Yaks::CollectionMapper, but you can subclass it for example to add links or attributes on the collection itself
161
180
  * `:rel` : Set the relation (symbol or URI) this association has with the object. Will be derived from the association name and the configured rel_template if ommitted
181
+ * `:link_if`: Conditionally render the association as a link. A `:href` option is required
182
+
183
+ ```ruby
184
+ class ShowMapper < Yaks::Mapper
185
+ has_many :events, href: '/show/{id}/events', link_if: ->{ events.count > 50 }
186
+ end
187
+ ```
162
188
 
163
189
  ## Namespace
164
190
 
@@ -236,13 +262,13 @@ If `env` contains a `HTTP_ACCEPT` key (Rack's way of representing the `Accept` h
236
262
 
237
263
  ## Custom attribute/link/subresource handling
238
264
 
239
- When inheriting from `Yaks::Mapper`, you can override `map_attributes`, `map_links` and `map_resources` to skip (or augment) above methods, and instead implement your own custom mechanism. For example
265
+ When inheriting from `Yaks::Mapper`, you can override `map_attributes`, `map_links` and `map_resources` to skip (or augment) above methods, and instead implement your own custom mechanism. These methods take a `Yaks::Resource` instance, and should return an updated resource. They should not alter the resource instance in-place. For example
240
266
 
241
267
  ```ruby
242
268
  class ErrorMapper < Yaks::Mapper
243
269
  link :profile, '/api/error'
244
270
 
245
- def map_attributes
271
+ def map_attributes(resource)
246
272
  attrs = {
247
273
  http_code: 500,
248
274
  message: object.to_s,
@@ -257,7 +283,7 @@ class ErrorMapper < Yaks::Mapper
257
283
  attrs[:type] = "record_not_found"
258
284
  end
259
285
 
260
- attrs
286
+ resource.update_attributes(attrs)
261
287
  end
262
288
  end
263
289
  ```
@@ -400,6 +426,10 @@ Yaks is used in production by [Ticketsolve](http://www.ticketsolve.com/). You ca
400
426
 
401
427
  Get in touch if you like to see your name and API here.
402
428
 
429
+ ## Demo
430
+
431
+ You can find an example app at [Yakports](https://github.com/plexus/yakports), or browse the HAL api directly using the [HAL browser](http://yaks-airports.herokuapp.com/browser.html).
432
+
403
433
  ## Acknowledgment
404
434
 
405
435
  The mapper syntax is largely borrowed from ActiveModel::Serializers, which in turn closely mimics the syntax of ActiveRecord models. It's a great concise syntax that still offers plenty of flexibility, so to not reinvent the wheel I've stuck to the existing syntax as far as practical, although there are several extensions and deviations.
@@ -416,7 +446,7 @@ If this approach sounds appealing, have a look at [microrb.com](http://microrb.c
416
446
 
417
447
  ## How to contribute
418
448
 
419
- Run the tests, the examples, try it with your own stuff and leave your impressions in the issues. Or discuss on API-craft.
449
+ Run the tests, the examples, try it with your own stuff and leave your impressions in the issues. Or discuss on [API-craft](https://groups.google.com/d/forum/api-craft).
420
450
 
421
451
  To fix a bug
422
452
 
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rubygems/package_task'
2
+ require 'yaks'
2
3
 
3
4
  spec = Gem::Specification.load(Pathname.glob('*.gemspec').first.to_s)
4
5
  Gem::PackageTask.new(spec).define
@@ -19,3 +20,35 @@ task :mutant do
19
20
  result = Mutant::CLI.run(%w[-Ilib -ryaks --use rspec --score 100] + opts + [pattern])
20
21
  fail unless result == Mutant::CLI::EXIT_SUCCESS
21
22
  end
23
+
24
+ task :mutant_chunked do
25
+ [
26
+ # Yaks::Util,
27
+ # Yaks::Primitivize,
28
+ Yaks::FP,
29
+ Yaks::Resource,
30
+ Yaks::NullResource,
31
+ Yaks::CollectionResource,
32
+ Yaks::Mapper::Association,
33
+ Yaks::Mapper::AssociationMapper,
34
+ Yaks::Mapper::HasMany,
35
+ Yaks::Mapper::HasOne,
36
+ Yaks::Mapper::Config,
37
+ Yaks::Mapper::ClassMethods,
38
+ Yaks::Mapper::Attribute,
39
+ Yaks::Format,
40
+ Yaks::Config::DSL,
41
+ Yaks::CollectionMapper,
42
+ Yaks::Mapper::Link,
43
+ Yaks::Format::JsonApi,
44
+ Yaks::DefaultPolicy, # 45/249 (81.93%)
45
+ Yaks::Format::CollectionJson, # 15/183 (91.80%)
46
+ Yaks::Format::Hal, # 17/209 (91.87%)
47
+ Yaks::Mapper, # 12/203 (94.09%)
48
+ Yaks::Config, # 12/263 (95.44%)
49
+ ].each do |space|
50
+ puts space
51
+ ENV['PATTERN'] = "#{space}"
52
+ Rake::Task["mutant"].execute
53
+ end
54
+ end
@@ -0,0 +1,22 @@
1
+ module Yaks
2
+
3
+ BreakingChanges = {
4
+ '0.4.3' => %q~
5
+
6
+ Breaking Changes in Yaks 0.4.3
7
+ ==============================
8
+
9
+ Yaks::Mapper#filter was removed, if you override this method in your
10
+ mappers to conditionally filter attributes or associations, you will
11
+ have to override #attributes or #associations instead.
12
+
13
+ When specifying a rel_template, now a single {rel} placeholder is
14
+ expected instead of {src} and {dest}.
15
+
16
+ There are other internal changes. See the CHANGELOG and README for full
17
+ documentation.
18
+
19
+ ~
20
+ }
21
+
22
+ end
@@ -4,48 +4,45 @@ module Yaks
4
4
  class CollectionMapper < Mapper
5
5
  alias collection object
6
6
 
7
- def initialize(context)
8
- super(context)
9
- end
10
-
11
- def member_mapper
12
- context.fetch(:member_mapper) do
13
- if collection.first
14
- mapper_for_model(collection.first)
15
- end
16
- end
17
- end
18
-
7
+ # @param [Array] collection
8
+ # @return [Array]
19
9
  def call(collection)
20
10
  @object = collection
21
11
 
22
12
  attrs = {
23
13
  type: collection_type,
24
- links: map_links,
25
- attributes: map_attributes,
26
14
  members: collection().map do |obj|
27
15
  mapper_for_model(obj).new(context).call(obj)
28
16
  end
29
17
  }
30
18
 
31
- attrs[ :members_rel ] = members_rel if members_rel
19
+ attrs[ :collection_rel ] = collection_rel
32
20
 
33
- CollectionResource.new(attrs)
21
+ map_attributes(
22
+ map_links(
23
+ CollectionResource.new(attrs)
24
+ )
25
+ )
34
26
  end
35
27
 
36
28
  private
37
29
 
38
- def members_rel
39
- policy.expand_rel( 'collection', pluralize( collection_type ) ) if collection_type
30
+ def collection_rel
31
+ if collection_type
32
+ policy.expand_rel( pluralize( collection_type ) )
33
+ else
34
+ 'collection'
35
+ end
40
36
  end
41
37
 
42
38
  def collection_type
43
- return unless member_mapper
44
- member_mapper.config.type || policy.derive_type_from_mapper_class(member_mapper)
39
+ if item_mapper = context[:item_mapper]
40
+ item_mapper.config.type || policy.derive_type_from_mapper_class(item_mapper)
41
+ end
45
42
  end
46
43
 
47
44
  def mapper_for_model(model)
48
- context.fetch(:member_mapper) do
45
+ context.fetch(:item_mapper) do
49
46
  policy.derive_mapper_from_object(model)
50
47
  end
51
48
  end
@@ -15,19 +15,30 @@ module Yaks
15
15
  # In the second case a collection has a single "subresource", being its
16
16
  # members.
17
17
  class CollectionResource < Resource
18
- include Equalizer.new(:type, :links, :attributes, :members, :members_rel)
18
+ include Equalizer.new(:type, :links, :attributes, :members, :collection_rel)
19
+ include FP::HashUpdatable.new(:type, :links, :attributes, :members, :collection_rel)
19
20
  include Enumerable
20
21
 
21
22
  extend Forwardable
22
23
 
23
- attr_reader :type, :links, :members, :members_rel
24
+ # @!attribute [r] type
25
+ # @return [String]
26
+ # @!attribute [r] links
27
+ # @return [Array]
28
+ # @!attribute [r] members
29
+ # @return [Array]
30
+ # @!attribute [r] collection_rel
31
+ # @return [String]
32
+ attr_reader :type, :links, :members, :collection_rel
24
33
 
25
34
  def_delegators :members, :each
26
35
 
36
+ # @param [Hash] options
37
+ # @return [CollectionResource]
27
38
  def initialize(options)
28
39
  super
29
40
  @members = options.fetch(:members, [])
30
- @members_rel = options.fetch(:members_rel, 'members')
41
+ @collection_rel = options.fetch(:collection_rel, 'members')
31
42
  end
32
43
 
33
44
  # Make a CollectionResource quack like a resource.
@@ -37,20 +48,23 @@ module Yaks
37
48
  # whatever it gets as a single resource with links and subresources,
38
49
  # we just push the collection down one level.
39
50
  #
40
- # Once inside subresources the HAL serializer does check if a resource
51
+ # Once inside subresources the HAL format does check if a resource
41
52
  # is a collection, since there it does make a distinction, and because
42
53
  # in that case it will iterate with each/map rather than calling subresources,
43
54
  # this doesn't cause infinite recursion. Not very pretty, needs looking at.
44
55
  #
45
56
  # :(
57
+ #
58
+ # @return [Hash]
46
59
  def subresources
47
60
  if any?
48
- { members_rel => self }
61
+ { collection_rel => self }
49
62
  else
50
63
  {}
51
64
  end
52
65
  end
53
66
 
67
+ # @return [Boolean]
54
68
  def collection?
55
69
  true
56
70
  end
@@ -0,0 +1,78 @@
1
+ module Yaks
2
+ class Config
3
+ class DSL
4
+ # @!attribute [r] config
5
+ # @return [Yaks::Config]
6
+ attr_reader :config
7
+
8
+ # @param [Yaks::Config] config
9
+ # @param [Proc] blk
10
+ # @return [Yaks::Config::DSL]
11
+ def initialize(config, &blk)
12
+ @config = config
13
+ @policy_class = Class.new(DefaultPolicy)
14
+ @policies = []
15
+ instance_eval(&blk) if blk
16
+ @policies.each do |policy_blk|
17
+ @policy_class.class_eval &policy_blk
18
+ end
19
+ config.policy_class = @policy_class
20
+ end
21
+
22
+ # @param [Symbol] format
23
+ # @return [Symbol]
24
+ def format_options(format, options)
25
+ config.format_options[format] = options
26
+ end
27
+
28
+ # @param [Symbol] format
29
+ # @return [Symbol]
30
+ def default_format(format)
31
+ config.default_format = format
32
+ end
33
+
34
+ # @param [Object] klass
35
+ # @return [Object]
36
+ def policy(klass)
37
+ @policy_class = klass
38
+ end
39
+
40
+ # @param [String] templ
41
+ # @return [String]
42
+ def rel_template(templ)
43
+ config.policy_options[:rel_template] = templ
44
+ end
45
+
46
+ # @param [Object] namespace
47
+ # @return [Object]
48
+ def mapper_namespace(namespace)
49
+ config.policy_options[:namespace] = namespace
50
+ end
51
+ alias namespace mapper_namespace
52
+
53
+ # @param [Array] args
54
+ # @param [Proc] blk
55
+ # @return [Array]
56
+ def map_to_primitive(*args, &blk)
57
+ config.primitivize.map(*args, &blk)
58
+ end
59
+
60
+ # @param [Proc] block
61
+ # @return [Array]
62
+ def after(&block)
63
+ config.steps << block
64
+ end
65
+
66
+ # Will define each method available in the DefaultPolicy upon the DSL
67
+ # and then make it available to apply to any Class taking on the
68
+ # `@policies` Array.
69
+ DefaultPolicy.public_instance_methods(false).each do |method|
70
+ define_method method do |&blk|
71
+ @policies << proc {
72
+ define_method method, &blk
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
data/lib/yaks/config.rb CHANGED
@@ -1,85 +1,56 @@
1
1
  module Yaks
2
2
  class Config
3
- class DSL
4
- attr_reader :config
5
-
6
- def initialize(config, &blk)
7
- @config = config
8
- @policy_class = Class.new(DefaultPolicy)
9
- @policies = []
10
- instance_eval(&blk) if blk
11
- @policies.each do |policy_blk|
12
- @policy_class.class_eval &policy_blk
13
- end
14
- config.policy_class = @policy_class
15
- end
16
-
17
- def format_options(format, options)
18
- config.format_options[format] = options
19
- end
20
-
21
- def default_format(format)
22
- config.default_format = format
23
- end
24
-
25
- def policy(klass)
26
- @policy_class = klass
27
- end
28
-
29
- def rel_template(templ)
30
- config.policy_options[:rel_template] = templ
31
- end
32
-
33
- def mapper_namespace(namespace)
34
- config.policy_options[:namespace] = namespace
35
- end
36
- alias namespace mapper_namespace
37
-
38
- def map_to_primitive(*args, &blk)
39
- config.primitivize.map(*args, &blk)
40
- end
41
-
42
- def after(&block)
43
- config.steps << block
44
- end
45
-
46
- DefaultPolicy.public_instance_methods(false).each do |method|
47
- define_method method do |&blk|
48
- @policies << proc {
49
- define_method method, &blk
50
- }
51
- end
52
- end
53
- end
54
3
 
4
+ # @!attribute [rw] format_options
5
+ # @return [Hash]
6
+ # @!attribute [rw] default_format
7
+ # @return [Symbol]
8
+ # @!attribute [rw] policy_class
9
+ # @return [Constant]
10
+ # @!attribute [rw] policy_options
11
+ # @return [Hash]
12
+ # @!attribute [rw] primitivize
13
+ # @return [Boolean]
14
+ # @!attribute [rw] steps
15
+ # @return [Array]
55
16
  attr_accessor :format_options, :default_format, :policy_class, :policy_options, :primitivize, :steps
56
17
 
18
+ # @param [Proc] blk
19
+ # @return [Yaks::Config]
57
20
  def initialize(&blk)
58
21
  @format_options = Hash.new({})
59
22
  @default_format = :hal
60
23
  @policy_options = {}
61
24
  @primitivize = Primitivize.create
62
- @steps = [ @primitivize ]
25
+ @steps = [
26
+ @primitivize
27
+ ]
63
28
  DSL.new(self, &blk)
64
29
  end
65
30
 
31
+ # @return [Yaks::DefaultPolicy, Object]
66
32
  def policy
67
33
  @policy_class.new(@policy_options)
68
34
  end
69
35
 
70
- def serializer_class(opts, env)
71
- if env.key? 'HTTP_ACCEPT'
72
- accept = Rack::Accept::Charset.new(env['HTTP_ACCEPT'])
73
- mime_type = accept.best_of(Serializer.mime_types.values)
74
- return Serializer.by_mime_type(mime_type) if mime_type
75
- end
76
- Serializer.by_name(opts.fetch(:format) { @default_format })
36
+ # @param [Hash] opts
37
+ # @param [Hash] env
38
+ # @return [Yaks::Format::CollectionJson, Yaks::Format::Hal, Yaks::Format::JsonApi]
39
+ def format_class(opts, env)
40
+ accept = Rack::Accept::Charset.new(env['HTTP_ACCEPT'])
41
+ mime_type = accept.best_of(Format.mime_types.values)
42
+ return Format.by_mime_type(mime_type) if mime_type
43
+ Format.by_name(opts.fetch(:format) { @default_format })
77
44
  end
78
45
 
46
+ # @param [Hash] opts
47
+ # @return [String]
79
48
  def format_name(opts)
80
49
  opts.fetch(:format) { @default_format }
81
50
  end
82
51
 
52
+ # @param [Symbol] format
53
+ # @return [Object]
83
54
  def options_for_format(format)
84
55
  format_options[format]
85
56
  end
@@ -87,7 +58,10 @@ module Yaks
87
58
  # model => Yaks::Resource
88
59
  # Yaks::Resource => serialized structure
89
60
  # serialized structure => serialized flat
90
-
61
+ #
62
+ # @param [Object] object
63
+ # @param [Hash] opts
64
+ # @return [Object]
91
65
  def call(object, opts = {})
92
66
  env = opts.fetch(:env, {})
93
67
  context = {
@@ -96,10 +70,10 @@ module Yaks
96
70
  mapper_stack: []
97
71
  }
98
72
 
99
- mapper = opts.fetch(:mapper) { policy.derive_mapper_from_object(object) }.new(context)
100
- serializer = serializer_class(opts, env).new(format_options[format_name(opts)])
73
+ mapper = opts.fetch(:mapper) { policy.derive_mapper_from_object(object) }.new(context)
74
+ format = format_class(opts, env).new(format_options[format_name(opts)])
101
75
 
102
- [ mapper, serializer, *steps ].inject(object) {|memo, step| step.call(memo) }
76
+ [ mapper, format, *steps ].inject(object) {|memo, step| step.call(memo) }
103
77
  end
104
78
  alias serialize call
105
79
  end