yaks 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2011212cb9c579cebb6ee58228407bdfde224829
4
- data.tar.gz: 96d967888e80337c38850db63923bac9a74446e9
3
+ metadata.gz: a609ab5341e17172a098a296e8935d9abf4fa995
4
+ data.tar.gz: 44f4ef2d6d7786bf09261b352ed9e253064ff31e
5
5
  SHA512:
6
- metadata.gz: f6aa331742aabedbf57d46182d72029664f385af6d844bc92b1180e3aa8d0e956782deab1d2406ef8cebac36dbbea57189675a6d558d992dae6f37fd1bf12ad6
7
- data.tar.gz: c53bec9f2219b58e7f2d6cd16b0966ec1ceeadc9507556c21569746e753e43fa6e65e7bd099f2b6cbe6d5943476824eea28ec6118beeffbef1665e5bb210cb9e
6
+ metadata.gz: f65c4f9d62853543fc92fbe58fc9a3c4b057eac27473a951d8cfe38edf19cf0af461bd9e047e20cbce47ab771ded553b859937e6c8dff7e1a25aa2f1101f8a18
7
+ data.tar.gz: be7d5c1edcc4e745a25897deae315000d1bdff1713b8a6d61876f36d62d4dc866792a5f362957c7218e64e7a9c346bec38bd064e7297cfa33be26702b451bd33
data/README.md CHANGED
@@ -2,11 +2,13 @@
2
2
  [![Build Status](https://secure.travis-ci.org/plexus/yaks.png?branch=master)][travis]
3
3
  [![Dependency Status](https://gemnasium.com/plexus/yaks.png)][gemnasium]
4
4
  [![Code Climate](https://codeclimate.com/github/plexus/yaks.png)][codeclimate]
5
+ [![Gitter](https://badges.gitter.im/Join Chat.svg)][gitter]
5
6
 
6
7
  [gem]: https://rubygems.org/gems/yaks
7
8
  [travis]: https://travis-ci.org/plexus/yaks
8
9
  [gemnasium]: https://gemnasium.com/plexus/yaks
9
10
  [codeclimate]: https://codeclimate.com/github/plexus/yaks
11
+ [gitter]: https://gitter.im/plexus/yaks?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
10
12
 
11
13
  # Yaks
12
14
 
@@ -22,6 +24,7 @@ requested. These formats are presently supported:
22
24
  * Collection+JSON
23
25
  * HTML
24
26
  * HALO
27
+ * Transit
25
28
 
26
29
  ## State of Development
27
30
 
@@ -309,9 +312,15 @@ If `env` contains a `HTTP_ACCEPT` key (Rack's way of representing the
309
312
  `Accept` header), Yaks will return the format that most closely
310
313
  matches what was requested.
311
314
 
315
+ <a id="namespace"></a>
316
+
312
317
  ## Namespace
313
318
 
314
- Yaks by default will find your mappers for you if they follow the naming convention of appending 'Mapper' to the model class name. This (and all other "conventions") can be easily redefined though, see below. If you have your mappers inside a module, use `namespace`.
319
+ Yaks by default will find your mappers for you if they follow the
320
+ naming convention of appending 'Mapper' to the model class name. This
321
+ (and all other "conventions") can be easily redefined though, see the
322
+ <a href="#policy">policy</a> section. If you have your mappers inside a
323
+ module, use `namespace`.
315
324
 
316
325
  ```ruby
317
326
  module API
@@ -327,7 +336,8 @@ yaks = Yaks.new do
327
336
  end
328
337
  ```
329
338
 
330
- If your namespace contains a `CollectionMapper`, Yaks will use that instead of `Yaks::CollectionMapper`, e.g.
339
+ If your namespace contains a `CollectionMapper`, Yaks will use that
340
+ instead of `Yaks::CollectionMapper`, e.g.
331
341
 
332
342
  ```ruby
333
343
  module API
@@ -339,7 +349,8 @@ module API
339
349
  end
340
350
  ```
341
351
 
342
- You can also have collection mappers based on the type of members the collection holds, e.g.
352
+ You can also have collection mappers based on the type of members the
353
+ collection holds, e.g.
343
354
 
344
355
  ```ruby
345
356
  module API
@@ -358,12 +369,20 @@ module API
358
369
  end
359
370
  ```
360
371
 
361
- Yaks will automatically detect and use this collection when serializing an array of `LineItem` objects.
372
+ Yaks will automatically detect and use this collection when
373
+ serializing an array of `LineItem` objects. See <a
374
+ href="#derive_mapper_from_object">derive_mapper_from_object</a> for
375
+ details.
362
376
 
363
377
 
364
378
  ## Custom attribute/link/subresource handling
365
379
 
366
- 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
380
+ When inheriting from `Yaks::Mapper`, you can override
381
+ `map_attributes`, `map_links` and `map_resources` to skip (or augment)
382
+ above methods, and instead implement your own custom mechanism. These
383
+ methods take a `Yaks::Resource` instance, and should return an updated
384
+ resource. They should not alter the resource instance in-place. For
385
+ example
367
386
 
368
387
  ```ruby
369
388
  class ErrorMapper < Yaks::Mapper
@@ -441,6 +460,9 @@ HAL. To stick close to the spec you're best to create your own
441
460
  singular types that represent collections, rather than rendering a top
442
461
  level CollectionResource.
443
462
 
463
+ Yaks also has a derived format called HALO, which is a non-standard
464
+ extension to HAL which includes form elements.
465
+
444
466
  ### HTML
445
467
 
446
468
  The hypermedia format *par excellence*. Yaks can generate a version of
@@ -511,11 +533,20 @@ class PostMapper < Yaks::Mapper
511
533
  end
512
534
  ```
513
535
 
514
- Subresources aren't mapped because Collection+JSON doesn't really have that concept.
536
+ Subresources aren't mapped because Collection+JSON doesn't really have
537
+ that concept.
538
+
539
+ ### Transit
540
+
541
+ There is experimental support for Transit. The transit gem handles
542
+ serialization internally, so there is no intermediate document. The
543
+ `format` step already returns the serialized string.
515
544
 
516
545
  ## Hooks
517
546
 
518
- It is possible to hook into the Yaks pipeline to perform extra processing steps before, after, or around each step. It also possible to skip a step.
547
+ It is possible to hook into the Yaks pipeline to perform extra
548
+ processing steps before, after, or around each step. It also possible
549
+ to skip a step.
519
550
 
520
551
  ``` ruby
521
552
  yaks = Yaks.new do
@@ -530,6 +561,8 @@ yaks = Yaks.new do
530
561
  end
531
562
  ```
532
563
 
564
+ <a id="policy"></a>
565
+
533
566
  ## Policy over Configuration
534
567
 
535
568
  It's an old adage in the Ruby/Rails world to have "Convention over Configuration", mostly to derive values that were not given explicitly. Typically based on things having similar names and a 1-1 derivable relationship.
@@ -574,7 +607,89 @@ yaks = Yaks.new do
574
607
  end
575
608
  ```
576
609
 
577
- <a id="primitivizer">
610
+ <a id="derive_mapper_from_object"></a>
611
+
612
+ ### derive_mapper_from_object
613
+
614
+ This is called when trying to serialize something and no explicit
615
+ mapper is given. To recap, it's always possible to be explicit, e.g.
616
+
617
+ ```
618
+ yaks.call(widget, mapper: WidgetMapper)
619
+ yaks.call(array_of_widgets, mapper: MyCollectionMapper, item_mapper: WidgetMapper)
620
+ ```
621
+
622
+ If the mapper is left unspecified, Yaks will inspect whatever you pass
623
+ it, and try various constant lookups based on naming. These all happen
624
+ in the configured namespace, which defaults to the Ruby top level.
625
+
626
+ If the object responds to `to_ary` it is considered a collection. If
627
+ the first object in the collection has a class of `Widget`, and the
628
+ configured namespace is `API`, then these are tried in turn
629
+
630
+ * `API::WidgetCollectionMapper`
631
+ * `API::CollectionMapper`
632
+ * `Yaks::CollectionMapper`
633
+
634
+ Note that Yaks can only find a specific collection mapper for a type
635
+ if the collection passed to Yaks contains at least one element. If
636
+ it's important that empty collections are handled by the right mapper
637
+ (e.g. to set a specific `self` or `profile` link), then you have to be
638
+ explicit.
639
+
640
+ If the object is not a collection, then lookup happens based on the
641
+ class name, and will traverse up the class hierarchy if no suitable
642
+ mapper is found. So for a `class Widget < Thing`, yaks would look for
643
+
644
+ * `API::WidgetMapper`
645
+ * `API::ThingMapper`
646
+ * `API::ObjectMapper`
647
+
648
+ If none of these are found an error is raised.
649
+
650
+ ### derive_mapper_from_association
651
+
652
+ When no mapper is specified for an association, then this method is
653
+ called to find the right mapper, based on the association name. In
654
+ case of `has_many` collections this is the "item mapper", the
655
+ collection mapper is resolved using `derive_mapper_from_object`.
656
+
657
+ By default the mapper class is derived from the name of the association, e.g.
658
+
659
+ ```
660
+ has_many :widgets #=> WidgetMapper
661
+ has_one :widget #=> WidgetMapper
662
+ ```
663
+
664
+ It is always possible to explicitly set a mapper.
665
+
666
+ ```
667
+ has_one :widget, mapper: FooMapper
668
+ has_many :widgets, collection_mapper: MyCollectionMapper, mapper: FooMapper
669
+ ```
670
+
671
+ ### derive_rel_from_association
672
+
673
+ Associations have a "rel", an IANA registered identifier or fully
674
+ qualified URI, that specifies how the object relates to the parent
675
+ document.
676
+
677
+ When configuring Yaks one can set a `rel_template`, that will be used
678
+ to generate these rels if not explicitly given. The `rel` placeholder
679
+ in the template will be substituted with the association name.
680
+
681
+ ``` ruby
682
+ yaks = Yaks.new do
683
+ rel_template "http://api.example.com/rel/{rel}"
684
+ end
685
+
686
+ # ... mapper
687
+
688
+ has_many :widgets #=> rel: "http://api.example.com/rel/widgets"
689
+ has_one :widget #=> rel: "http://api.example.com/rel/widget"
690
+ ```
691
+
692
+ <a id="primitivizer"></a>
578
693
 
579
694
  ## Primitivizer
580
695
 
@@ -603,7 +718,7 @@ end
603
718
  Yaks by default "primitivizes" symbols (as strings), and classes that include Enumerable (as arrays).
604
719
 
605
720
 
606
- <a id="integration">
721
+ <a id="integration"></a>
607
722
 
608
723
  ## Integration
609
724
 
@@ -36,8 +36,16 @@ module Yaks
36
36
  end
37
37
  CollectionMapper
38
38
  else
39
+ klass = model.class
40
+ begin
41
+ name = klass.name.split('::').last
42
+ return @options[:namespace].const_get(name + 'Mapper')
43
+ rescue NameError
44
+ klass = klass.superclass
45
+ retry if klass
46
+ end
39
47
  name = model.class.name.split('::').last
40
- @options[:namespace].const_get(name + 'Mapper')
48
+ raise "Failed to find a mapper for #{model.inspect}. Did you mean to implement #{name}Mapper?"
41
49
  end
42
50
  end
43
51
 
data/lib/yaks/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yaks
2
- VERSION = '0.8.2'
2
+ VERSION = '0.8.3'
3
3
  end
@@ -1,11 +1,13 @@
1
1
  # Used by Yaks::DefaultPolicy* tests to test various name inference schemes
2
2
 
3
3
  class SoyMapper ; end
4
- class Soy ; end
4
+ class Bean ; end
5
+ class Soy < Bean; end
5
6
  class Wheat ; end
6
7
 
7
8
  module MyMappers
8
9
  class SoyMapper ; end
10
+ class BeanMapper ; end
9
11
  end
10
12
 
11
13
  class SoyCollectionMapper ; end
@@ -13,6 +15,12 @@ class SoyCollectionMapper ; end
13
15
  module Namespace
14
16
  module Nested
15
17
  class Rye ; end
18
+ class Mung < Bean
19
+ alias inspect to_s # on 1.9 inspect calls to_s
20
+ def to_s
21
+ "mungbean"
22
+ end
23
+ end
16
24
  end
17
25
 
18
26
  class RyeMapper ; end
@@ -75,4 +75,20 @@ RSpec.describe Yaks::DefaultPolicy, '#derive_mapper_from_object' do
75
75
  end
76
76
  end
77
77
 
78
+ context 'when a mapper exists for a superclass' do
79
+ let(:options) { {namespace: MyMappers} }
80
+
81
+ it 'should use the superclass mapper' do
82
+ expect(policy.derive_mapper_from_object(Namespace::Nested::Mung.new)).to be(MyMappers::BeanMapper)
83
+ end
84
+ end
85
+
86
+ context 'when no mapper is found' do
87
+ it 'should give a nice message' do
88
+ expect {
89
+ policy.derive_mapper_from_object(Namespace::Nested::Mung.new)
90
+ }.to raise_error /Failed to find a mapper for #<Namespace::Nested::Mung:0x\h+>. Did you mean to implement MungMapper\?/
91
+ end
92
+ end
93
+
78
94
  end
data/yaks.gemspec CHANGED
@@ -34,8 +34,8 @@ Gem::Specification.new do |gem|
34
34
  gem.add_development_dependency 'bogus'
35
35
  gem.add_development_dependency 'rake'
36
36
  gem.add_development_dependency 'yard'
37
- gem.add_development_dependency 'mutant-rspec'
38
- gem.add_development_dependency 'mutant'
37
+ gem.add_development_dependency 'mutant-rspec' if RUBY_VERSION > '1.9'
38
+ gem.add_development_dependency 'mutant' if RUBY_VERSION > '1.9'
39
39
  gem.add_development_dependency 'rspec-its'
40
40
  gem.add_development_dependency 'benchmark-ips'
41
41
  gem.add_development_dependency 'yaks-html'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arne Brasseur
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-02 00:00:00.000000000 Z
11
+ date: 2015-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inflection