roar 0.12.9 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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