roar-rails 0.1.6 → 1.0.0
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.
- checksums.yaml +4 -4
- data/CHANGES.markdown +5 -0
- data/Gemfile +1 -1
- data/README.markdown +12 -8
- data/gemfiles/Gemfile.rails3-0 +2 -0
- data/gemfiles/Gemfile.rails3-2 +1 -0
- data/lib/roar-rails.rb +4 -6
- data/lib/roar/rails/controller_additions.rb +26 -10
- data/lib/roar/rails/hal.rb +3 -3
- data/lib/roar/rails/railtie.rb +5 -0
- data/lib/roar/rails/responder.rb +1 -1
- data/lib/roar/rails/validations_representer.rb +3 -3
- data/lib/roar/rails/version.rb +1 -1
- data/roar-rails.gemspec +3 -3
- data/test/consume_test.rb +64 -2
- data/test/dummy/app/representers/band_representer.rb +2 -2
- data/test/dummy/app/representers/singer_alias_representer.rb +1 -1
- data/test/dummy/app/representers/singer_representer.rb +2 -2
- data/test/json_hal_renderer_test.rb +5 -13
- data/test/render_test.rb +1 -1
- data/test/responder_test.rb +44 -5
- data/test/test_helper.rb +9 -0
- metadata +66 -52
- data/test/dummy/Rakefile +0 -7
- data/test/dummy/app/helpers/application_helper.rb +0 -2
- data/test/dummy/app/views/layouts/application.html.erb +0 -14
- data/test/dummy/app/views/musician/featured.html.erb +0 -1
- data/test/dummy/app/views/musician/featured_with_block.html.erb +0 -4
- data/test/dummy/app/views/musician/hamlet.html.haml +0 -1
- data/test/dummy/config/locales/en.yml +0 -5
- data/test/dummy/public/404.html +0 -26
- data/test/dummy/public/422.html +0 -26
- data/test/dummy/public/500.html +0 -26
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/javascripts/application.js +0 -2
- data/test/dummy/public/javascripts/controls.js +0 -965
- data/test/dummy/public/javascripts/dragdrop.js +0 -974
- data/test/dummy/public/javascripts/effects.js +0 -1123
- data/test/dummy/public/javascripts/prototype.js +0 -4874
- data/test/dummy/public/javascripts/rails.js +0 -118
- data/test/dummy/public/stylesheets/.gitkeep +0 -0
- data/test/dummy/script/rails +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1dbecd0bbc7e521087763fd2ff0313d7d3cda940
|
4
|
+
data.tar.gz: 3b14e95c24d51ee0003f97c4c079dafc62a40699
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bcfc77fe5ff9d9e0fdb48d962bad6ffd2f44fcbd7446d31b4fbf3f1c14bbadad93ead2356103024f2923d0d1104f0317c93398d5ede28b5e5beaa499d4b30d8
|
7
|
+
data.tar.gz: 87b69c8d04bfbf819c32b0bbe2dca74ac929d374f315837a87d449a76656eaf2b0ba090ef93b605bfeaa0579c34f91070c768f3f886be9e1902059dffebeb73c
|
data/CHANGES.markdown
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
## 1.0.0
|
2
|
+
|
3
|
+
* Requires Roar >= 1.0.0.
|
4
|
+
* In `#consume!` roar-rails now finds the correct representer for the `Content-type:` header. In former version the representer name was infered using the `Accept:` header, which was totally wrong. Thanks to @pgaertig for fixing that.
|
5
|
+
|
1
6
|
## 0.1.6
|
2
7
|
|
3
8
|
* Added `ControllerAdditions::Render` to support `#render` in controller actions with representers.
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -32,7 +32,7 @@ This will create the file `app/representers/band_representer.rb` with the follow
|
|
32
32
|
|
33
33
|
```ruby
|
34
34
|
module BandRepresenter
|
35
|
-
include Roar::
|
35
|
+
include Roar::JSON
|
36
36
|
|
37
37
|
property :id
|
38
38
|
property :name
|
@@ -129,6 +129,7 @@ end
|
|
129
129
|
## Parsing incoming documents
|
130
130
|
|
131
131
|
In `#create` and `#update` actions it is often necessary to parse the incoming representation and map it to a model instance. Use the `#consume!` method for this.
|
132
|
+
The client must provide a `Content-Type` request header with proper MIME type to let `#consume!` know which representer to use.
|
132
133
|
|
133
134
|
```ruby
|
134
135
|
class SingersController < ApplicationController
|
@@ -143,17 +144,20 @@ class SingersController < ApplicationController
|
|
143
144
|
end
|
144
145
|
```
|
145
146
|
|
146
|
-
|
147
|
+
For instance, if content type is set to `application/xml` the `consume!` call will roughly do the following.
|
147
148
|
|
148
149
|
```ruby
|
149
150
|
singer.
|
150
151
|
extend(SingerRepresenter)
|
151
|
-
|
152
|
+
from_xml(request.body)
|
152
153
|
```
|
153
154
|
|
154
|
-
So, `#consume!` helps you figuring out the representer module and reading the incoming document.
|
155
|
+
So, `#consume!` helps you figuring out the representer module and reading the incoming document. Just like Rails, depending on the registered MIME type for `Content-type` it picks the deserialize method (e.g. `from_json` vs. `from_xml`)
|
155
156
|
|
156
|
-
|
157
|
+
It is important to provide a known content type in the request. If it is missing or not supported by the responder
|
158
|
+
`#consume!` will raise an exception `Roar::Rails::ControllerAdditions::UnsupportedMediaType`. Unless you rescue the exception the action will stop and respond with HTTP status `406 Unsupported Media Type`.
|
159
|
+
|
160
|
+
Note that `#consume!` respects settings from `#represents`. It uses the same mechanics known from `#respond_with` to choose a representer.
|
157
161
|
|
158
162
|
```ruby
|
159
163
|
consume!(singer, :represent_with => MusicianRepresenter)
|
@@ -165,7 +169,7 @@ If you prefer roar's decorator approach over extend, just go for it. roar-rails
|
|
165
169
|
|
166
170
|
```ruby
|
167
171
|
class SingerRepresenter < Roar::Decorator
|
168
|
-
include Roar::
|
172
|
+
include Roar::JSON
|
169
173
|
|
170
174
|
property :name
|
171
175
|
|
@@ -211,8 +215,8 @@ Any URL helpers from the Rails app are automatically available in representers.
|
|
211
215
|
|
212
216
|
```ruby
|
213
217
|
module FruitRepresenter
|
214
|
-
include Roar::
|
215
|
-
include Roar::
|
218
|
+
include Roar::JSON
|
219
|
+
include Roar::Hypermedia
|
216
220
|
|
217
221
|
link :self do
|
218
222
|
fruit_url self
|
data/gemfiles/Gemfile.rails3-0
CHANGED
data/gemfiles/Gemfile.rails3-2
CHANGED
data/lib/roar-rails.rb
CHANGED
@@ -3,17 +3,15 @@ require "roar/representer"
|
|
3
3
|
require "roar/decorator"
|
4
4
|
require "roar/rails/railtie"
|
5
5
|
|
6
|
-
module Roar
|
7
|
-
autoload("XML", "roar/
|
8
|
-
autoload("JSON", "roar/
|
6
|
+
module Roar
|
7
|
+
autoload("XML", "roar/xml")
|
8
|
+
autoload("JSON", "roar/json")
|
9
9
|
|
10
10
|
module JSON
|
11
11
|
autoload("HAL", "roar/rails/hal")
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
autoload("Hypermedia", "roar/representer/feature/hypermedia")
|
16
|
-
end
|
14
|
+
autoload("Hypermedia", "roar/hypermedia")
|
17
15
|
end
|
18
16
|
|
19
17
|
|
@@ -17,17 +17,22 @@ module Roar::Rails
|
|
17
17
|
|
18
18
|
module ClassMethods
|
19
19
|
def represents(format, options)
|
20
|
-
represents_options.add(format,options)
|
20
|
+
represents_options.add(format, options)
|
21
21
|
respond_to format
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
|
26
|
+
# TODO: move into separate class so we don't pollute controller.
|
26
27
|
def consume!(model, options={})
|
27
|
-
|
28
|
+
content_type = request.content_type
|
29
|
+
|
30
|
+
format = Mime::Type.lookup(content_type).try(:symbol) or raise UnsupportedMediaType.new("Cannot consume unregistered media type '#{content_type.inspect}'")
|
31
|
+
|
32
|
+
parsing_method = compute_parsing_method(format)
|
28
33
|
representer = prepare_model_for(format, model, options)
|
29
34
|
|
30
|
-
representer.send(
|
35
|
+
representer.send(parsing_method, incoming_string, options) # e.g. from_json("...")
|
31
36
|
model
|
32
37
|
end
|
33
38
|
|
@@ -52,15 +57,23 @@ module Roar::Rails
|
|
52
57
|
body.read
|
53
58
|
end
|
54
59
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
+
# These methods deal with interfacing between the Roar Response object and
|
61
|
+
# ActionController, they simply pass the body of the Roar response up or do nothing
|
62
|
+
def _render_option_json(resource, options)
|
63
|
+
super(_resource_or_body(resource), options)
|
64
|
+
end
|
60
65
|
|
61
|
-
|
66
|
+
def _render_option_xml(resource, options)
|
67
|
+
super(_resource_or_body(resource), options)
|
62
68
|
end
|
63
69
|
|
70
|
+
def _render_option_hal(resource, options)
|
71
|
+
super(_resource_or_body(resource), options)
|
72
|
+
end
|
73
|
+
|
74
|
+
def _resource_or_body(resource)
|
75
|
+
resource.is_a?(Roar::Rails::Responder::Response) ? resource.body : resource
|
76
|
+
end
|
64
77
|
|
65
78
|
# Include if you intend to use roar-rails with <tt>render json: model</tt>.
|
66
79
|
module Render
|
@@ -70,4 +83,7 @@ module Roar::Rails
|
|
70
83
|
end
|
71
84
|
end
|
72
85
|
end
|
73
|
-
|
86
|
+
|
87
|
+
class UnsupportedMediaType < StandardError #:nodoc:
|
88
|
+
end
|
89
|
+
end
|
data/lib/roar/rails/hal.rb
CHANGED
data/lib/roar/rails/railtie.rb
CHANGED
@@ -6,6 +6,11 @@ module Roar
|
|
6
6
|
class Railtie < ::Rails::Railtie
|
7
7
|
config.representer = ActiveSupport::OrderedOptions.new
|
8
8
|
|
9
|
+
rescue_responses = config.action_dispatch.rescue_responses || ActionDispatch::ShowExceptions.rescue_responses #newer or fallback to 3.0
|
10
|
+
rescue_responses.merge!(
|
11
|
+
'Roar::Rails::ControllerAdditions::UnsupportedMediaType' => :unsupported_media_type
|
12
|
+
)
|
13
|
+
|
9
14
|
initializer "roar.set_configs" do |app|
|
10
15
|
::Roar::Representer.module_eval do
|
11
16
|
include app.routes.url_helpers
|
data/lib/roar/rails/responder.rb
CHANGED
@@ -6,14 +6,14 @@ module ValidatorsRepresenter
|
|
6
6
|
class ValidatorClient
|
7
7
|
attr_accessor :kind, :options
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
# Represents a single Validator instance.
|
11
11
|
module ValidatorRepresenter
|
12
|
-
include Roar::
|
12
|
+
include Roar::JSON
|
13
13
|
property :kind
|
14
14
|
hash :options
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
# Represents an array of validators for an attribute.
|
18
18
|
module AttributeValidators
|
19
19
|
include Representable::JSON::Collection
|
data/lib/roar/rails/version.rb
CHANGED
data/roar-rails.gemspec
CHANGED
@@ -18,13 +18,13 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_runtime_dependency "roar", ">= 0.
|
21
|
+
s.add_runtime_dependency "roar", ">= 1.0.0", "<= 1.1.0"
|
22
22
|
s.add_runtime_dependency "test_xml", ">= 0.1.6" # TODO: remove dependency as most people don't use XML.
|
23
23
|
s.add_runtime_dependency "actionpack"
|
24
24
|
s.add_runtime_dependency "railties", ">= 3.0.0"
|
25
|
-
s.add_runtime_dependency "uber"
|
25
|
+
s.add_runtime_dependency "uber", ">= 0.0.5"
|
26
26
|
|
27
|
-
s.add_development_dependency "minitest"
|
27
|
+
s.add_development_dependency "minitest"
|
28
28
|
s.add_development_dependency "activemodel"
|
29
29
|
s.add_development_dependency "activerecord"
|
30
30
|
s.add_development_dependency "sqlite3"
|
data/test/consume_test.rb
CHANGED
@@ -16,16 +16,33 @@ class ConsumeTest < ActionController::TestCase
|
|
16
16
|
tests UnnamespaceSingersController
|
17
17
|
|
18
18
|
test "#consume parses incoming document and updates the model" do
|
19
|
-
|
19
|
+
@request.env['CONTENT_TYPE'] = 'application/json'
|
20
|
+
post :consume_json, "{\"name\": \"Bumi\"}"
|
20
21
|
assert_equal %{#<struct Singer name="Bumi">}, @response.body
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
25
|
+
class ConsumeHalWithNoHalRespondTest < ActionController::TestCase
|
26
|
+
include Roar::Rails::TestCase
|
27
|
+
|
28
|
+
tests UnnamespaceSingersController
|
29
|
+
|
30
|
+
# Content-type is set properly, it's a registered mime but responder doesn't do #from_hal.
|
31
|
+
# FIXME: why does that still find a representer?
|
32
|
+
test "#consume parses hal document and updates the model" do
|
33
|
+
@request.env['CONTENT_TYPE'] = 'application/hal+json'
|
34
|
+
# assert_raises Roar::Rails::UnsupportedMediaType do
|
35
|
+
assert_raises NoMethodError do # currently, we don't know if a format is supported in general, or not.
|
36
|
+
post :consume_json, "{\"name\": \"Bumi\"}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
24
41
|
class ConsumeWithConfigurationTest < ActionController::TestCase
|
25
42
|
include Roar::Rails::TestCase
|
26
43
|
|
27
44
|
module MusicianRepresenter
|
28
|
-
include Roar::
|
45
|
+
include Roar::JSON
|
29
46
|
property :name, :as => :called
|
30
47
|
end
|
31
48
|
|
@@ -44,9 +61,52 @@ class ConsumeWithConfigurationTest < ActionController::TestCase
|
|
44
61
|
tests SingersController
|
45
62
|
|
46
63
|
test "#consume uses ConsumeWithConfigurationTest::MusicianRepresenter to parse incoming document" do
|
64
|
+
@request.env['CONTENT_TYPE'] = 'application/json'
|
47
65
|
post :consume_json, %{{"called":"Bumi"}}, :format => :json
|
48
66
|
assert_equal %{#<struct Singer name="Bumi">}, @response.body
|
49
67
|
end
|
68
|
+
|
69
|
+
test "#do not consume missing content type" do
|
70
|
+
assert_raises Roar::Rails::UnsupportedMediaType do
|
71
|
+
post :consume_json, "{\"name\": \"Bumi\"}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
test "#do not consume parses unknown content type" do
|
77
|
+
@request.env['CONTENT_TYPE'] = 'application/custom+json'
|
78
|
+
assert_raises Roar::Rails::UnsupportedMediaType do
|
79
|
+
post :consume_json, "{\"name\": \"Bumi\"}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class ConsumeHalTest < ActionController::TestCase
|
85
|
+
include Roar::Rails::TestCase
|
86
|
+
|
87
|
+
module MusicianRepresenter
|
88
|
+
include Roar::JSON::HAL
|
89
|
+
property :name
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
class SingersController < ActionController::Base
|
94
|
+
include Roar::Rails::ControllerAdditions
|
95
|
+
represents :hal, :entity => MusicianRepresenter
|
96
|
+
|
97
|
+
def consume_hal
|
98
|
+
singer = consume!(Singer.new)
|
99
|
+
render :text => singer.inspect
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
tests SingersController
|
104
|
+
|
105
|
+
test "#consume parses HAL document and updates the model" do
|
106
|
+
@request.env['CONTENT_TYPE'] = 'application/hal+json'
|
107
|
+
post :consume_hal, "{\"name\": \"Bumi\"}"
|
108
|
+
assert_equal %{#<struct Singer name="Bumi">}, @response.body
|
109
|
+
end
|
50
110
|
end
|
51
111
|
|
52
112
|
class ConsumeWithOptionsOverridingConfigurationTest < ActionController::TestCase
|
@@ -66,6 +126,7 @@ class ConsumeWithOptionsOverridingConfigurationTest < ActionController::TestCase
|
|
66
126
|
tests SingersController
|
67
127
|
|
68
128
|
test "#consume uses #represents config to parse incoming document" do
|
129
|
+
@request.env['CONTENT_TYPE'] = 'application/json'
|
69
130
|
post :consume_json, %{{"called":"Bumi"}}, :format => :json
|
70
131
|
assert_equal %{#<struct Singer name="Bumi">}, @response.body
|
71
132
|
end
|
@@ -73,6 +134,7 @@ end
|
|
73
134
|
|
74
135
|
class RequestBodyStringTest < ConsumeTest
|
75
136
|
test "#read rewinds before reading" do
|
137
|
+
@request.env['CONTENT_TYPE'] = 'application/json'
|
76
138
|
@request.instance_eval do
|
77
139
|
def body
|
78
140
|
incoming = super
|
@@ -1,19 +1,11 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
Mime::Type.register 'application/json+hal', :hal
|
4
|
-
if Roar::Rails.rails_version >= 4.1
|
5
|
-
ActionController.add_renderer :hal do |js, options|
|
6
|
-
self.content_type ||= Mime::HAL
|
7
|
-
js.to_json
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
3
|
class HalRendererTest < ActionController::TestCase
|
12
4
|
include Roar::Rails::TestCase
|
13
5
|
|
14
6
|
class SingersController < ActionController::Base
|
15
7
|
module HalSingerRepresenter
|
16
|
-
include Roar::
|
8
|
+
include Roar::JSON::HAL
|
17
9
|
|
18
10
|
property :name
|
19
11
|
link(:self) { "http://#{name}" }
|
@@ -30,13 +22,13 @@ class HalRendererTest < ActionController::TestCase
|
|
30
22
|
|
31
23
|
tests SingersController
|
32
24
|
|
33
|
-
test "should render correctly in response to a application/json
|
25
|
+
test "should render correctly in response to a application/hal+json request" do
|
34
26
|
get :show, :id => "bumi", :format => :hal
|
35
27
|
assert_body '{"name":"Bumi","_links":{"self":{"href":"http://Bumi"}}}'
|
36
28
|
end
|
37
29
|
|
38
|
-
test "should have a content_type of application/json
|
30
|
+
test "should have a content_type of application/hal+json" do
|
39
31
|
get :show, :id => "bumi", :format => :hal
|
40
|
-
assert_equal response.content_type, 'application/json
|
32
|
+
assert_equal response.content_type, 'application/hal+json'
|
41
33
|
end
|
42
|
-
end
|
34
|
+
end
|