roar-rails 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,7 +3,7 @@
3
3
  *.swo
4
4
  bin
5
5
  .bundle
6
- Gemfile.lock
6
+ Gemfile*.lock
7
7
  pkg/*
8
8
  test/dummy/log/*
9
9
  .rvmrc
data/CHANGES.markdown CHANGED
@@ -1,3 +1,7 @@
1
+ h2. 0.0.12
2
+
3
+ * Bumping representable to 1.4 which allows us using both extend and decorating representers.
4
+
1
5
  h2. 0.0.11
2
6
 
3
7
  * Back to `request.body.read` in `#consume!` (again). If anyone is having problems with empty incoming strings this is a Rails issue - update ;-)
data/README.markdown CHANGED
@@ -100,7 +100,7 @@ class SingersController < ApplicationController
100
100
  def create
101
101
  singer = Singer.new
102
102
  consume!(singer)
103
-
103
+
104
104
  respond_with singer
105
105
  end
106
106
  end
@@ -122,6 +122,18 @@ Note that it respects settings from `#represents`. It uses the same mechanics kn
122
122
  consume!(singer, :represent_with => MusicianRepresenter)
123
123
  ```
124
124
 
125
+ ## Using Decorators
126
+
127
+ If you prefer roar's decorator approach over extend, just go for it. roar-rails will figure out automatically which represent strategy to use.
128
+
129
+ ```ruby
130
+ class SingerRepresenter < Roar::Decorator
131
+ include Roar::Representer::JSON
132
+
133
+ property :name
134
+ end
135
+ ```
136
+
125
137
  ## URL Helpers
126
138
 
127
139
  Any URL helpers from the Rails app are automatically available in representers.
@@ -1,6 +1,6 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in roar-rails.gemspec
4
- gemspec path: '../'
4
+ gemspec :path => '../'
5
5
 
6
6
  gem 'railties', '~> 3.0.11'
@@ -1,6 +1,6 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in roar-rails.gemspec
4
- gemspec path: '../'
4
+ gemspec :path => '../'
5
5
 
6
6
  gem 'railties', '~> 3.2.0'
@@ -37,10 +37,16 @@ module Roar::Rails
37
37
 
38
38
 
39
39
  def consume!(model, options={})
40
- format = formats.first # FIXME: i expected request.content_mime_type to do the job. copied from responder.rb. this will return the wrong format when the controller responds to :json and :xml and the Content-type is :xml (?)
40
+ format = formats.first # FIXME: i expected request.content_mime_type to do the job. copied from responder.rb. this will return the wrong format when the controller responds to :json and :xml and the Content-type is :xml (?)
41
+ model = prepare_model_for(format, model, options)
42
+
43
+ model.send(compute_parsing_method(format), incoming_string) # e.g. from_json("...")
44
+ model
45
+ end
46
+
47
+ def prepare_model_for(format, model, options)
41
48
  representer = representer_for(format, model, options)
42
49
  extend_with!(model, representer)
43
- model.send(compute_parsing_method(format), incoming_string) # e.g. from_json("...")
44
50
  model
45
51
  end
46
52
 
@@ -4,7 +4,7 @@ module Roar::Rails
4
4
  def prepare_model!(model)
5
5
  # rails <= 3.1 compatibility. #display gets called for empty responses
6
6
  # >= 3.2 fixes by calling #head, not #display for all empty bodies (PUT, DELETE)
7
- return if respond_to?("empty_#{format}_resource") && model == empty_resource
7
+ return model if respond_to?("empty_#{format}_resource") && model == empty_resource
8
8
  super
9
9
  end
10
10
  end
@@ -2,31 +2,30 @@ module Roar::Rails
2
2
  module ModelMethods
3
3
  private
4
4
  # DISCUSS: move this into a generic namespace as we could need that in Sinatra as well.
5
- def extend_with!(model, representer)
6
- model.extend(representer)
5
+ def extend_with!(model, representer) # TODO: rename to #prepare_model.
6
+ representer.prepare(model)
7
7
  end
8
-
8
+
9
9
  def prepare_model!(model)
10
- representer = controller.representer_for(format, model, options)
11
- extend_with!(model, representer)
10
+ controller.prepare_model_for(format, model, options)
12
11
  end
13
12
  end
14
-
13
+
15
14
  module Responder
16
15
  include ModelMethods
17
-
16
+
18
17
  # DISCUSS: why THE FUCK is options not passed as a method argument but kept as an internal instance variable in the responder? this is something i will never understand about Rails.
19
18
  def display(model, *args)
20
19
  if representer = options.delete(:represent_items_with)
21
20
  render_items_with(model, representer) # convenience API, not recommended since it's missing hypermedia.
22
21
  return super
23
22
  end
24
-
25
- prepare_model!(model)
26
-
23
+
24
+ model = prepare_model!(model)
25
+
27
26
  super
28
27
  end
29
-
28
+
30
29
  private
31
30
  def render_items_with(collection, representer)
32
31
  collection.map! do |m| # DISCUSS: i don't like changing the method argument here.
@@ -34,7 +33,7 @@ module Roar::Rails
34
33
  m.to_hash # FIXME: huh? and what about XML?
35
34
  end
36
35
  end
37
-
36
+
38
37
  include VersionStrategy
39
38
  end
40
39
  end
@@ -1,5 +1,5 @@
1
1
  module Roar
2
2
  module Rails
3
- VERSION = "0.0.11"
3
+ VERSION = "0.0.12"
4
4
  end
5
5
  end
data/roar-rails.gemspec CHANGED
@@ -17,13 +17,14 @@ Gem::Specification.new do |s|
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
-
20
+
21
21
  s.add_runtime_dependency "roar", "~> 0.10"
22
+ s.add_runtime_dependency "representable", "~> 1.4"
22
23
  s.add_runtime_dependency "test_xml"
23
24
  s.add_runtime_dependency "actionpack", "~> 3.0"
24
25
  s.add_runtime_dependency "railties", "~> 3.0"
25
26
  s.add_runtime_dependency "hooks"
26
-
27
+
27
28
  s.add_development_dependency "minitest", ">= 2.8.1"
28
29
  s.add_development_dependency "tzinfo" # FIXME: why the hell do we need this for 3.1?
29
30
  end
@@ -4,7 +4,7 @@ Singer = Struct.new(:name)
4
4
 
5
5
  module SingersRepresenter
6
6
  include Roar::Representer::JSON
7
-
7
+
8
8
  collection :singers, :extend => SingerRepresenter
9
9
  def singers
10
10
  each
@@ -19,13 +19,13 @@ end
19
19
  class RepresentsTest < MiniTest::Spec
20
20
  class SingersController
21
21
  end
22
-
22
+
23
23
  before do
24
24
  @controller = Class.new do
25
25
  include Roar::Rails::ControllerAdditions
26
26
  end.new
27
27
  end
28
-
28
+
29
29
  describe "representer_for" do
30
30
  describe "nothing configured" do
31
31
  before do
@@ -34,16 +34,16 @@ class RepresentsTest < MiniTest::Spec
34
34
  self
35
35
  end.new
36
36
  end
37
-
37
+
38
38
  it "uses model class" do
39
39
  assert_equal SingerRepresenter, @controller.representer_for(:json, Singer.new)
40
40
  end
41
-
41
+
42
42
  it "uses plural controller name when collection" do
43
43
  assert_equal SingersRepresenter, @controller.representer_for(:json, [])
44
44
  end
45
45
  end
46
-
46
+
47
47
  describe "represents :json, Singer" do
48
48
  before do
49
49
  @controller = class ::WhateverController < ActionController::Base
@@ -52,17 +52,17 @@ class RepresentsTest < MiniTest::Spec
52
52
  self
53
53
  end.new
54
54
  end
55
-
55
+
56
56
  it "uses defined class for item" do
57
57
  assert_equal ObjectRepresenter, @controller.representer_for(:json, Singer.new)
58
58
  end
59
-
59
+
60
60
  it "uses plural name when collection" do
61
61
  assert_equal ObjectsRepresenter, @controller.representer_for(:json, [])
62
62
  end
63
63
  end
64
-
65
-
64
+
65
+
66
66
  describe "represents :json, :entity => SingerRepresenter" do
67
67
  before do
68
68
  @controller = class ::FooController < ActionController::Base
@@ -71,16 +71,16 @@ class RepresentsTest < MiniTest::Spec
71
71
  self
72
72
  end.new
73
73
  end
74
-
74
+
75
75
  it "returns :entity representer name" do
76
76
  assert_equal "ObjectRepresenter", @controller.representer_for(:json, Singer.new)
77
77
  end
78
-
78
+
79
79
  it "doesn't infer collection representer" do
80
80
  assert_equal nil, @controller.representer_for(:json, [])
81
81
  end
82
82
  end
83
-
83
+
84
84
  describe "represents :json, :entity => SingerRepresenter, :collection => SingersRepresenter" do
85
85
  before do
86
86
  @controller = class ::BooController < ActionController::Base
@@ -89,11 +89,11 @@ class RepresentsTest < MiniTest::Spec
89
89
  self
90
90
  end.new
91
91
  end
92
-
92
+
93
93
  it "uses defined class for item" do
94
94
  assert_equal "ObjectRepresenter", @controller.representer_for(:json, Singer.new)
95
95
  end
96
-
96
+
97
97
  it "uses defined class when collection" do
98
98
  assert_equal "SingersRepresenter", @controller.representer_for(:json, [])
99
99
  end
@@ -104,11 +104,11 @@ end
104
104
 
105
105
  class ResponderTest < ActionController::TestCase
106
106
  include Roar::Rails::TestCase
107
-
107
+
108
108
  class BaseController < ActionController::Base
109
109
  include Roar::Rails::ControllerAdditions
110
110
  respond_to :json
111
-
111
+
112
112
  def execute
113
113
  instance_exec &@block
114
114
  end
@@ -138,16 +138,16 @@ class ResponderTest < ActionController::TestCase
138
138
  singer = Singer.new("Bumi")
139
139
  respond_with singer
140
140
  end
141
-
141
+
142
142
  assert_equal singer.to_json, @response.body
143
143
  end
144
-
144
+
145
145
  test "responder finds SingersRepresenter for collections by convention" do
146
146
  get do
147
147
  singers = [Singer.new("Bumi"), Singer.new("Bjork"), Singer.new("Sinead")]
148
148
  respond_with singers
149
149
  end
150
-
150
+
151
151
  assert_equal({:singers => singers.collect {|s| s.extend(SingerRepresenter).to_hash }}.to_json, @response.body)
152
152
  end
153
153
 
@@ -165,68 +165,90 @@ class ResponderTest < ActionController::TestCase
165
165
  class SingersController < BaseController
166
166
  represents :json, Object
167
167
  end
168
-
168
+
169
169
  tests SingersController
170
-
170
+
171
171
  test "responder uses passed representer" do
172
172
  get do
173
173
  singer = Singer.new("Bumi")
174
174
  respond_with singer, :represent_with => SingerRepresenter
175
175
  end
176
-
176
+
177
177
  assert_equal singer.to_json, @response.body
178
178
  end
179
-
179
+
180
180
  test "responder uses passed representer for collection" do
181
181
  get do
182
182
  singers = [Singer.new("Bumi"), Singer.new("Bjork"), Singer.new("Sinead")]
183
183
  respond_with singers, :represent_with => SingersRepresenter
184
184
  end
185
-
185
+
186
186
  assert_equal({:singers => singers.collect {|s| s.extend(SingerRepresenter).to_hash }}.to_json, @response.body)
187
187
  end
188
-
188
+
189
189
  test "responder uses passed representer for collection items when :represent_items_with set" do
190
190
  get do
191
191
  singers = [Singer.new("Bumi"), Singer.new("Bjork"), Singer.new("Sinead")]
192
192
  respond_with singers, :represent_items_with => SingerRepresenter
193
193
  end
194
-
194
+
195
195
  assert_equal(singers.collect {|s| s.extend(SingerRepresenter).to_hash }.to_json, @response.body)
196
196
  end
197
197
  end
198
-
198
+
199
199
  class ConfiguredControllerTest < ResponderTest
200
200
  class MusicianController < BaseController
201
201
  represents :json, :entity => SingerRepresenter, :collection => SingersRepresenter
202
202
  end
203
-
203
+
204
204
  tests MusicianController
205
-
205
+
206
206
  test "responder uses configured representer" do
207
207
  get do
208
208
  singer = Singer.new("Bumi")
209
209
  respond_with singer
210
210
  end
211
-
211
+
212
212
  assert_equal singer.to_json, @response.body
213
213
  end
214
-
214
+
215
215
  test "responder uses configured representer for collection" do
216
216
  get do
217
217
  singers = [Singer.new("Bumi"), Singer.new("Bjork"), Singer.new("Sinead")]
218
218
  respond_with singers
219
219
  end
220
-
220
+
221
221
  assert_equal({:singers => singers.collect {|s| s.extend(SingerRepresenter).to_hash }}.to_json, @response.body)
222
222
  end
223
223
  end
224
-
224
+
225
+ class ControllerWithDecoratorTest < ResponderTest
226
+ class SingerRepresentation < Representable::Decorator
227
+ include Roar::Representer::JSON
228
+ include ::SingerRepresenter
229
+ end
230
+ class MusicianController < BaseController
231
+ represents :json, :entity => SingerRepresentation
232
+ end
233
+
234
+ tests MusicianController
235
+
236
+ test "responder uses configured decorating representer" do
237
+ get do
238
+ singer = Singer.new("Bumi")
239
+ respond_with singer
240
+ end
241
+
242
+ assert_equal "{\"name\":\"Bumi\"}", @response.body
243
+ end
244
+ end
245
+
246
+
225
247
  def get(&block)
226
248
  @controller.instance_eval do
227
249
  @block = block
228
250
  end
229
-
251
+
230
252
  super :execute, :format => 'json'
231
253
  end
232
254
 
@@ -236,7 +258,7 @@ class ResponderTest < ActionController::TestCase
236
258
  end
237
259
  super :execute, :format => 'json'
238
260
  end
239
-
261
+
240
262
  def singer(name="Bumi")
241
263
  singer = Musician.new(name)
242
264
  singer.extend SingerRepresenter
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roar-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.12
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-06 00:00:00.000000000 Z
12
+ date: 2013-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: roar
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0.10'
30
+ - !ruby/object:Gem::Dependency
31
+ name: representable
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.4'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.4'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: test_xml
32
48
  requirement: !ruby/object:Gem::Requirement