roar 0.12.9 → 1.0.0.beta1

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +8 -10
  4. data/CHANGES.markdown +24 -2
  5. data/Gemfile +5 -2
  6. data/README.markdown +132 -28
  7. data/TODO.markdown +9 -7
  8. data/examples/example.rb +2 -0
  9. data/examples/example_server.rb +19 -3
  10. data/gemfiles/Gemfile.representable-2.0 +5 -0
  11. data/gemfiles/Gemfile.representable-2.1 +5 -0
  12. data/lib/roar.rb +1 -1
  13. data/lib/roar/client.rb +38 -0
  14. data/lib/roar/{representer/feature/coercion.rb → coercion.rb} +2 -1
  15. data/lib/roar/decorator.rb +3 -11
  16. data/lib/roar/http_verbs.rb +88 -0
  17. data/lib/roar/hypermedia.rb +174 -0
  18. data/lib/roar/json.rb +55 -0
  19. data/lib/roar/json/collection.rb +3 -0
  20. data/lib/roar/{representer/json → json}/collection_json.rb +20 -20
  21. data/lib/roar/{representer/json → json}/hal.rb +33 -31
  22. data/lib/roar/json/hash.rb +3 -0
  23. data/lib/roar/json/json_api.rb +208 -0
  24. data/lib/roar/representer.rb +3 -36
  25. data/lib/roar/transport/faraday.rb +49 -0
  26. data/lib/roar/transport/net_http.rb +57 -0
  27. data/lib/roar/transport/net_http/request.rb +72 -0
  28. data/lib/roar/version.rb +1 -1
  29. data/lib/roar/xml.rb +54 -0
  30. data/roar.gemspec +5 -4
  31. data/test/client_test.rb +3 -3
  32. data/test/coercion_feature_test.rb +6 -3
  33. data/test/collection_json_test.rb +8 -10
  34. data/test/decorator_test.rb +27 -15
  35. data/test/faraday_http_transport_test.rb +13 -15
  36. data/test/hal_json_test.rb +16 -16
  37. data/test/hal_links_test.rb +3 -3
  38. data/test/http_verbs_test.rb +17 -22
  39. data/test/hypermedia_feature_test.rb +23 -45
  40. data/test/hypermedia_test.rb +11 -23
  41. data/test/integration/band_representer.rb +2 -2
  42. data/test/integration/runner.rb +4 -3
  43. data/test/integration/server.rb +13 -2
  44. data/test/integration/ssl_server.rb +1 -1
  45. data/test/json_api_test.rb +336 -0
  46. data/test/json_representer_test.rb +16 -12
  47. data/test/lib/runner.rb +134 -0
  48. data/test/lonely_test.rb +9 -0
  49. data/test/net_http_transport_test.rb +4 -4
  50. data/test/representer_test.rb +2 -2
  51. data/test/{lib/roar/representer/transport/net_http/request_test.rb → ssl_client_certs_test.rb} +43 -5
  52. data/test/test_helper.rb +12 -5
  53. data/test/xml_representer_test.rb +26 -166
  54. metadata +49 -29
  55. data/gemfiles/Gemfile.representable-1.7 +0 -6
  56. data/gemfiles/Gemfile.representable-1.8 +0 -6
  57. data/lib/roar/representer/feature/client.rb +0 -39
  58. data/lib/roar/representer/feature/http_verbs.rb +0 -95
  59. data/lib/roar/representer/feature/hypermedia.rb +0 -175
  60. data/lib/roar/representer/json.rb +0 -67
  61. data/lib/roar/representer/transport/faraday.rb +0 -50
  62. data/lib/roar/representer/transport/net_http.rb +0 -59
  63. data/lib/roar/representer/transport/net_http/request.rb +0 -75
  64. data/lib/roar/representer/xml.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bcbcc9501060b58047a296ceab9a48a3dd235251
4
- data.tar.gz: 45ada5410ffee101229c7f07edf8bf33f80e5c45
3
+ metadata.gz: 52b7f8314b58e3ebc06ca5dde920c82d8584b16b
4
+ data.tar.gz: 005bfc57c05c3a67ed3d7f1a778f1052c5d087c7
5
5
  SHA512:
6
- metadata.gz: 18f9be695ec8707c8bf5591aa669d6dcc38cc65c0b41eba490f54146298d9284eb7be8afd1dffcd6f121f862b230bce1cd14459d224b4f2ac62003122f7a3bca
7
- data.tar.gz: 2d47ba5c28f74c6cc4952db4a298b90ad618a7b6730cfac6286c43773d1a05284fac56bea603f1b310f7752c1b888a7f5a9de12d08bf5d503e25866e186b530a
6
+ metadata.gz: 9c06fc967e1c3f389e4ad87a144c78b516fc32267dea3bd0d5bacd99b7cc3e102faadeaec32c06dc4887526e74b95b745452210d13042aff727bd238f127f8f4
7
+ data.tar.gz: 497ac335d8ad6d65df546e8bff9e3c148fd204872d608a48580dce62334f082838f9e213cbaec7dd2c38b2c822073a661796e0c1eae3ebb04206a5a1778262c8
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ pkg/*
2
2
  *.gem
3
3
  .bundle
4
4
  Gemfile*.lock
5
+ .idea
data/.travis.yml CHANGED
@@ -1,12 +1,10 @@
1
- matrix:
2
- include:
3
- - rvm: 1.9.3
4
- gemfile: gemfiles/Gemfile.representable-1.7
5
- - rvm: 2.0.0
6
- gemfile: gemfiles/Gemfile.representable-1.7
7
- - rvm: 1.9.3
8
- gemfile: gemfiles/Gemfile.representable-1.8
9
- - rvm: 2.0.0
10
- gemfile: gemfiles/Gemfile.representable-1.8
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1
5
+ - 2.2
6
+ gemfiles:
7
+ - gemfiles/Gemfile.representable-2.0
8
+ - gemfiles/Gemfile.representable-2.1
11
9
  notifications:
12
10
  irc: "irc.freenode.org#cells"
data/CHANGES.markdown CHANGED
@@ -1,6 +1,28 @@
1
- # 0.12.9
1
+ # 1.0.0
2
2
 
3
- * Very last release in 0.12. Adding support for SSL certs.
3
+ ## Breakage
4
+
5
+ * Removed `Representer` and `Feature` namespace. That means changes along the following.
6
+ * `Roar::Representer::Feature::Hypermedia` --> `Roar::Hypermedia`
7
+ * `Roar::Representer::JSON` --> `Roar::JSON`
8
+ * Removed positional arguments for `HttpVerbs#get` and friends.
9
+
10
+ ## Added
11
+
12
+ * `Roar::JSON::JsonApi` supports JSON-API. A big thanks to @oliverbarnes for his continous help, support and research on how to implement this standard.
13
+
14
+
15
+ ## Relevant
16
+
17
+ * `Hyperlink#to_hash` now returns stringified keys.
18
+ * Removed `Representer#before_serialize` hook. Override `#serialize` yourself.
19
+ * Represented#links now returns `nil` when no parsing has happened.
20
+ * Removed class methods `::from_json`, `::from_hash`, `::from_xml` and `::deserialize`. Please build the instance yourself and use something along `Song.new.from_json`.
21
+
22
+ ## Internals
23
+
24
+ * Remove the concept of ´links_array`. `Hyperlink` instances for rendering or that have been parsed are always stored in a `LinkCollection` that is available via `#links`.
25
+ * `Hypermedia` is now 43% simpler.
4
26
 
5
27
  # 0.12.8
6
28
 
data/Gemfile CHANGED
@@ -3,5 +3,8 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in roar.gemspec
4
4
  gemspec
5
5
 
6
- #gem "representable", :path => "../representable"
7
- gem "sinatra-contrib", :git => "git@github.com:apotonick/sinatra-contrib.git", :branch => "runner"
6
+ gem "representable", "~> 2.1.0"
7
+ # gem "representable", :path => "../representable"
8
+
9
+ # as long as this is not merged, i'll vendor the runner file.
10
+ # gem "sinatra-contrib", :git => "git@github.com:apotonick/sinatra-contrib.git", :branch => "runner"
data/README.markdown CHANGED
@@ -8,7 +8,7 @@ Roar is a framework for parsing and rendering REST documents. Nothing more.
8
8
 
9
9
  Representers let you define your API document structure and semantics. They allow both rendering representations from your models _and_ parsing documents to update your Ruby objects. The bi-directional nature of representers make them interesting for both server and client usage.
10
10
 
11
- Roar comes with built-in JSON, JSON-HAL and XML support. Its highly modulare architecture provides features like coercion, hypermedia, HTTP transport, client caching and more.
11
+ Roar comes with built-in JSON, JSON-HAL, JSON-API and XML support. Its highly modulare architecture provides features like coercion, hypermedia, HTTP transport, client caching and more.
12
12
 
13
13
  Roar is completely framework-agnostic and loves being used in web kits like Rails, Webmachine, Sinatra, Padrino, etc. If you use Rails, consider [roar-rails](https://github.com/apotonick/roar-rails) for an enjoyable integration.
14
14
 
@@ -24,10 +24,10 @@ If in need for a feature, make sure to check the [representable API docs](https:
24
24
  Let's see how representers work. They're fun to use.
25
25
 
26
26
  ```ruby
27
- require 'roar/representer/json'
27
+ require 'roar/json'
28
28
 
29
29
  module SongRepresenter
30
- include Roar::Representer::JSON
30
+ include Roar::JSON
31
31
 
32
32
  property :title
33
33
  end
@@ -81,7 +81,7 @@ Many people dislike `#extend` due to eventual performance issue or object pollut
81
81
  require 'roar/decorator'
82
82
 
83
83
  class SongRepresenter < Roar::Decorator
84
- include Roar::Representer::JSON
84
+ include Roar::JSON
85
85
 
86
86
  property :title
87
87
  end
@@ -107,7 +107,7 @@ Roar (or rather representable) also allows to map collections in documents.
107
107
 
108
108
  ```ruby
109
109
  module SongRepresenter
110
- include Roar::Representer::JSON
110
+ include Roar::JSON
111
111
 
112
112
  property :title
113
113
  collection :composers
@@ -140,7 +140,7 @@ Another representer to represent.
140
140
 
141
141
  ```ruby
142
142
  module AlbumRepresenter
143
- include Roar::Representer::JSON
143
+ include Roar::JSON
144
144
 
145
145
  property :title
146
146
  collection :songs, extend: SongRepresenter, class: Song
@@ -188,7 +188,7 @@ Sometimes you don't wanna create two separate representers - although it makes t
188
188
 
189
189
  ```ruby
190
190
  module AlbumRepresenter
191
- include Roar::Representer::JSON
191
+ include Roar::JSON
192
192
 
193
193
  property :title
194
194
 
@@ -207,7 +207,7 @@ Usually, when parsing, nested objects are created from scratch. If you want nest
207
207
 
208
208
  ```ruby
209
209
  module AlbumRepresenter
210
- include Roar::Representer::JSON
210
+ include Roar::JSON
211
211
 
212
212
  property :title
213
213
 
@@ -235,11 +235,11 @@ We're currently [working on](https://github.com/apotonick/roar/issues/85) better
235
235
  Roar provides coercion with the [virtus](https://github.com/solnic/virtus) gem.
236
236
 
237
237
  ```ruby
238
- require 'roar/representer/feature/coercion'
238
+ require 'roar/feature/coercion'
239
239
 
240
240
  module SongRepresenter
241
- include Roar::Representer::JSON
242
- include Roar::Representer::Feature::Coercion
241
+ include Roar::JSON
242
+ include Roar::Coercion
243
243
 
244
244
  property :title
245
245
  property :released_at, type: DateTime
@@ -269,8 +269,8 @@ Roar comes with built-in support for embedding and processing hypermedia in your
269
269
 
270
270
  ```ruby
271
271
  module SongRepresenter
272
- include Roar::Representer::JSON
273
- include Roar::Representer::Feature::Hypermedia
272
+ include Roar::JSON
273
+ include Roar::Hypermedia
274
274
 
275
275
  property :title
276
276
 
@@ -298,7 +298,7 @@ Sometimes you need more data in the link block. Data that's not available from t
298
298
 
299
299
  ```ruby
300
300
  module SongRepresenter
301
- include Roar::Representer::JSON
301
+ include Roar::JSON
302
302
 
303
303
  property :title
304
304
 
@@ -343,10 +343,10 @@ Simply by including a module you make your representer understand the media type
343
343
  The [HAL](http://stateless.co/hal_specification.html) format is a simple media type that defines embedded resources and hypermedia.
344
344
 
345
345
  ```ruby
346
- require 'roar/representer/json/hal'
346
+ require 'roar/json/hal'
347
347
 
348
348
  module SongRepresenter
349
- include Roar::Representer::JSON::HAL
349
+ include Roar::JSON::HAL
350
350
 
351
351
  property :title
352
352
 
@@ -360,7 +360,7 @@ Documentation for HAL can be found in the [API docs](http://rdoc.info/github/apo
360
360
 
361
361
  ### Hypermedia
362
362
 
363
- Including the `Roar::Representer::JSON::HAL` module adds some more DSL methods to your module. It still allows using `::link` but treats them slightly different.
363
+ Including the `Roar::JSON::HAL` module adds some more DSL methods to your module. It still allows using `::link` but treats them slightly different.
364
364
 
365
365
  ```ruby
366
366
  song.to_json
@@ -377,7 +377,7 @@ Nested, or embedded, resources can be defined using the `:embedded` option.
377
377
 
378
378
  ```ruby
379
379
  module AlbumRepresenter
380
- include Roar::Representer::JSON::HAL
380
+ include Roar::JSON::HAL
381
381
 
382
382
  property :title
383
383
 
@@ -397,7 +397,97 @@ album.to_json
397
397
 
398
398
  HAL keys nested resources under the `_embedded` key and then by their type.
399
399
 
400
- All HAL features in Roar are discussed in the [API docs](http://rdoc.info/github/apotonick/roar/Roar/Representer/JSON/HAL), including [array links](https://github.com/apotonick/roar/blob/master/lib/roar/representer/json/hal.rb#L176).
400
+ All HAL features in Roar are discussed in the [API docs](http://rdoc.info/github/apotonick/roar/Roar/Representer/JSON/HAL), including [array links](https://github.com/apotonick/roar/blob/master/lib/roar/json/hal.rb#L176).
401
+
402
+
403
+ ## JSON-API
404
+
405
+ Roar also supports [JSON-API](http://jsonapi.org/) - yay! It can render _and_ parse singular and collection documents.
406
+
407
+ ### Resource
408
+
409
+ A minimal representation can be defined as follows.
410
+
411
+ ```ruby
412
+ require 'roar/json/json_api'
413
+
414
+ module SongsRepresenter
415
+ include Roar::JSON::JsonApi
416
+ type :songs
417
+
418
+ property :id
419
+ property :title
420
+ end
421
+ ```
422
+
423
+ Properties of the represented model are defined in the root level.
424
+
425
+ ### Hypermedia
426
+
427
+ You can add links to `linked` models within the resource section.
428
+
429
+ ```ruby
430
+ module SongsRepresenter
431
+ # ...
432
+
433
+ has_one :composer
434
+ has_many :listeners
435
+ end
436
+ ```
437
+
438
+ Global `links` can be added using the familiar `::link` method (this is still WIP as the DSL is not final).
439
+
440
+ ```ruby
441
+ module SongsRepresenter
442
+ # ...
443
+
444
+ link "songs.album" do
445
+ {
446
+ type: "album",
447
+ href: "http://example.com/albums/{songs.album}"
448
+ }
449
+ end
450
+ end
451
+ ```
452
+
453
+ ### Compounds
454
+
455
+ To add compound models into the document, use `::compound`.
456
+
457
+ ```ruby
458
+ module SongsRepresenter
459
+ # ...
460
+
461
+ compound do
462
+ property :album do
463
+ property :id
464
+ property :title
465
+ end
466
+
467
+ collection :musicians do
468
+ property :name
469
+ end
470
+ end
471
+ ```
472
+
473
+ ### Usage
474
+
475
+ As JSON-API per definition can represent singular models and collections you have two entry points.
476
+
477
+ ```ruby
478
+ SongsRepresenter.prepare(Song.find(1)).to_json
479
+ SongsRepresenter.prepare(Song.new).from_json("..")
480
+ ```
481
+
482
+ Singular models can use the representer module directly.
483
+
484
+ ```ruby
485
+ SongsRepresenter.for_collection.prepare([Song.find(1), Song.find(2)]).to_json
486
+ SongsRepresenter.for_collection.prepare([Song.new, Song.new]).from_json("..")
487
+ ```
488
+
489
+
490
+ Parsing currently works great with singular documents - for collections, we are still working out how to encode the application semantics. Feel free to help.
401
491
 
402
492
 
403
493
  ## Collection+JSON
@@ -406,7 +496,7 @@ The [Collection+JSON media format](http://amundsen.com/media-types/collection/)
406
496
 
407
497
  ```ruby
408
498
  module SongRepresenter
409
- include Roar::Representer::JSON::CollectionJSON
499
+ include Roar::JSON::CollectionJSON
410
500
  version "1.0"
411
501
  href { "http://localhost/songs/" }
412
502
 
@@ -455,8 +545,8 @@ Consider the following shared representer.
455
545
 
456
546
  ```ruby
457
547
  module SongRepresenter
458
- include Roar::Representer::JSON
459
- include Roar::Representer::Feature::Hypermedia
548
+ include Roar::JSON
549
+ include Roar::Hypermedia
460
550
 
461
551
  property :title
462
552
  property :id
@@ -470,18 +560,18 @@ end
470
560
  In a client where you don't have access to the database it is common to use `OpenStruct` classes as domain objects.
471
561
 
472
562
  ```ruby
473
- require 'roar/representer/feature/client'
563
+ require 'roar/client'
474
564
 
475
565
  class Song < OpenStruct
476
- include Roar::Representer::JSON
566
+ include Roar::JSON
477
567
  include SongRepresenter
478
- include Roar::Representer::Feature::Client
568
+ include Roar::Client
479
569
  end
480
570
  ```
481
571
 
482
572
  ## HTTP Support
483
573
 
484
- The `Feature::Client` module mixes all necessary methods into the client class, e.g. it provides HTTP support
574
+ The `Client` module mixes all necessary methods into the client class, e.g. it provides HTTP support
485
575
 
486
576
  ```ruby
487
577
  song = Song.new(title: "Roxanne")
@@ -525,8 +615,22 @@ The HTTP verbs allow you to specify credentials for HTTP basic auth.
525
615
 
526
616
  ```ruby
527
617
  song.get(uri: "http://localhost:4567/songs/1", basic_auth: ["username", "secret_password"])
618
+
528
619
  ```
529
620
 
621
+ ### Client SSL certificates
622
+
623
+ (Only currently supported with Net:Http)
624
+
625
+ ```ruby
626
+ song.get(uri: "http://localhost:4567/songs/1", pem_file: "/path/to/client/cert.pem", ssl_verify_mode: OpenSSL::SSL::VERIFY_PEER)
627
+
628
+ ```
629
+
630
+ Note: ssl_verify_mode is not required and will default to ```OpenSSL::SSL::VERIFY_PEER)```
631
+
632
+
633
+
530
634
  ### Request customization
531
635
 
532
636
  All verbs yield the request object before the request is sent, allowing to modify it. It is a `Net::HTTP::Request` instance (unless you use Faraday).
@@ -544,7 +648,7 @@ Roar also comes with XML support.
544
648
  ```ruby
545
649
  module SongRepresenter
546
650
  include Roar::Representer::XML
547
- include Roar::Representer::Feature::Hypermedia
651
+ include Roar::Representer::Hypermedia
548
652
 
549
653
  property :title
550
654
  property :id
@@ -584,4 +688,4 @@ We also have a [mailing list](https://groups.google.com/forum/?fromgroups#!forum
584
688
 
585
689
  ## License
586
690
 
587
- Roar is released under the [MIT License](http://www.opensource.org/licenses/MIT).
691
+ Roar is released under the [MIT License](http://www.opensource.org/licenses/MIT).
data/TODO.markdown CHANGED
@@ -1,11 +1,13 @@
1
+ # 1.0
2
+
3
+ * merge client errors request
4
+ * simpler link for JSON-API?
5
+ * remove HttpVerbs deprecations
6
+
7
+ * Hyperlink representers => decrators. test hash representer with decorator (rpr)
8
+
9
+
1
10
  * Add proxies, so nested models can be lazy-loaded.
2
11
  * move #prepare_links! call to #_links or something so it doesn't need to be called in #serialize.
3
- * alias Roar::Representer to Representer
4
- * remove #before_serialize and just overwrite #serialize
5
12
  * abstract ::links_definition_options and move them out of the generic representers (JSON, XML).
6
- * make 1.8 tests work, again (hash ordering!)
7
-
8
- * release 1.0
9
- * representable 1.8, only.
10
- * revise Hypermedia
11
13
  * work on HAL-Object
data/examples/example.rb CHANGED
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
1
3
  require 'bundler'
2
4
  Bundler.setup
3
5
 
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
1
3
  require "bundler/setup"
2
4
  require "sinatra"
3
5
  require "ostruct"
@@ -9,10 +11,24 @@ get "/method" do
9
11
  end
10
12
 
11
13
  post "/songs" do
12
- '{"id":"1","title":"Roxanne","links":[{"rel":"self","href":"http://localhost/songs/1"}]}'
14
+ '{"id":"1","title":"Roxanne","links":[{"rel":"self","href":"http://localhost/songs/1"}]}'
13
15
  end
14
16
 
15
17
 
16
18
  get "/songs/1" do
17
- '{"id":"1","title":"Roxanne","links":[{"rel":"self","href":"http://localhost/songs/1"}]}'
18
- end
19
+ '{"id":"1","title":"Roxanne","links":[{"rel":"self","href":"http://localhost/songs/1"}]}'
20
+ end
21
+
22
+ post "/respond404" do
23
+ status 404
24
+ '{"id":"1","title":"Roxanne","links":[{"rel":"self","href":"http://localhost/songs/1"}],"revision":"2"}'
25
+ end
26
+
27
+ post "/respond407" do
28
+ status 407
29
+ end
30
+
31
+ get "/respond200" do
32
+ status 200
33
+ '{"id":"1","title":"Roxanne","links":[{"rel":"self","href":"http://localhost/songs/1"},"revision":"3"]}'
34
+ end