roar-rails 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.travis.yml +6 -0
- data/CHANGES.markdown +3 -0
- data/Gemfile +0 -2
- data/README.markdown +71 -5
- data/gemfiles/Gemfile.rails3-0 +6 -0
- data/lib/roar-rails.rb +1 -0
- data/lib/roar/rails/railtie.rb +1 -1
- data/lib/roar/rails/responder.rb +23 -0
- data/lib/roar/rails/test_case.rb +8 -8
- data/lib/roar/rails/url_methods.rb +1 -1
- data/lib/roar/rails/validations_representer.rb +25 -0
- data/lib/roar/rails/version.rb +1 -1
- data/roar-rails.gemspec +1 -1
- data/test/dummy/app/representers/singer_representer.rb +2 -2
- data/test/representer_test.rb +16 -2
- data/test/responder_test.rb +57 -0
- data/test/validations_test.rb +34 -0
- metadata +12 -5
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CHANGES.markdown
ADDED
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -4,26 +4,92 @@ _Makes using Roar's representers in your Rails app fun._
|
|
4
4
|
|
5
5
|
## Features
|
6
6
|
|
7
|
-
|
7
|
+
* Rendering with responders
|
8
|
+
* URL helpers in representers
|
9
|
+
* Better tests
|
10
|
+
* Autoloading
|
11
|
+
|
12
|
+
## Rendering with #respond_with
|
13
|
+
|
14
|
+
Easily render resources using representers with the built-in responder.
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
class SingersController < ApplicationController
|
18
|
+
respond_to :json
|
19
|
+
|
20
|
+
def show
|
21
|
+
singer = Singer.find_by_id(params[:id])
|
22
|
+
respond_with singer
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.responder
|
26
|
+
Class.new(super).send :include, Roar::Rails::Responder
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
```
|
31
|
+
|
32
|
+
Need to use a representer with a different name than your model? Pass it in using the `:with_representer` option:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
class SingersController < ApplicationController
|
36
|
+
respond_to :json
|
37
|
+
|
38
|
+
def show
|
39
|
+
singer = Musician.find_by_id(params[:id])
|
40
|
+
respond_with singer, :with_representer => SingerRepresenter
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.responder
|
44
|
+
Class.new(super).send :include, Roar::Rails::Responder
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Goes great with [Jose Valim's responders gem][responders]!
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class SingersController < ApplicationController
|
54
|
+
respond_to :json
|
55
|
+
|
56
|
+
responders Roar::Rails::Responder
|
57
|
+
|
58
|
+
def show
|
59
|
+
singer = Singer.find_by_id(params[:id])
|
60
|
+
respond_with singer
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
## URL Helpers
|
8
67
|
|
9
68
|
Any URL helpers from the Rails app are automatically available in representers.
|
10
69
|
|
11
70
|
```ruby
|
12
71
|
module FruitRepresenter
|
13
72
|
include Roar::Representer::JSON
|
14
|
-
|
73
|
+
|
15
74
|
link :self do
|
16
75
|
fruit_url self
|
17
76
|
end
|
18
77
|
```
|
78
|
+
To get the hyperlinks up and running, please make sure to set the right _host name_ in your environment files (config/environments):
|
19
79
|
|
20
|
-
|
80
|
+
```ruby
|
81
|
+
config.representer.default_url_options = {:host => "127.0.0.1:3000"}
|
82
|
+
```
|
21
83
|
|
22
|
-
|
84
|
+
## Testing
|
23
85
|
|
86
|
+
## Autoloading
|
24
87
|
|
88
|
+
Put your representers in `app/representers` and they will be autoloaded by Rails. Also, frequently used modules as media representers and features don't need to be required manually.
|
25
89
|
|
26
90
|
|
27
91
|
## Contributors
|
28
92
|
|
29
|
-
* [Railslove](http://www.railslove.de) and especially Michael Bumann [bumi] have heavily supported development of roar-rails ("resource :singers").
|
93
|
+
* [Railslove](http://www.railslove.de) and especially Michael Bumann [bumi] have heavily supported development of roar-rails ("resource :singers").
|
94
|
+
|
95
|
+
[responders]: https://github.com/plataformatec/responders
|
data/lib/roar-rails.rb
CHANGED
data/lib/roar/rails/railtie.rb
CHANGED
@@ -9,7 +9,7 @@ module Roar
|
|
9
9
|
initializer "roar.set_configs" do |app|
|
10
10
|
::Roar::Representer.module_eval do
|
11
11
|
include app.routes.url_helpers
|
12
|
-
include app.routes.mounted_helpers
|
12
|
+
include app.routes.mounted_helpers unless ::Rails::VERSION::MINOR == 0
|
13
13
|
|
14
14
|
include UrlMethods # provide an initial #default_url_options.
|
15
15
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Roar::Rails
|
2
|
+
module Responder
|
3
|
+
def extend_with_representer!(resource, representer=nil)
|
4
|
+
representer ||= representer_for_resource(resource)
|
5
|
+
resource.extend(representer)
|
6
|
+
end
|
7
|
+
def display(resource, given_options={})
|
8
|
+
if resource.respond_to?(:map!)
|
9
|
+
resource.map! do |r|
|
10
|
+
extend_with_representer!(r)
|
11
|
+
r.to_hash
|
12
|
+
end
|
13
|
+
else
|
14
|
+
extend_with_representer!(resource, options.delete(:with_representer))
|
15
|
+
end
|
16
|
+
super
|
17
|
+
end
|
18
|
+
private
|
19
|
+
def representer_for_resource(resource)
|
20
|
+
(resource.class.name + "Representer").constantize
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/roar/rails/test_case.rb
CHANGED
@@ -4,30 +4,30 @@ module Roar
|
|
4
4
|
def get(action, *args)
|
5
5
|
process(action, "GET", *args)
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def post(action, *args)
|
9
9
|
process(action, "POST", *args)
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def put(action, *args)
|
13
13
|
process(action, "PUT", *args)
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def delete(action, *args)
|
17
17
|
process(action, "DELETE", *args)
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def process(action, http_method, document="", params={})
|
21
21
|
if document.is_a?(Hash)
|
22
22
|
params = document
|
23
23
|
document = ""
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
request.env['RAW_POST_DATA'] = document
|
27
|
-
|
27
|
+
|
28
28
|
super(action, params, nil, nil, http_method) # FIXME: for Rails <=3.1, only.
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
module Assertions
|
32
32
|
require 'test_xml/test_unit'
|
33
33
|
def assert_body(body, options={})
|
@@ -35,7 +35,7 @@ module Roar
|
|
35
35
|
assert_equal body, response.body
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
include Assertions
|
40
40
|
end
|
41
41
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'representable/json/collection'
|
2
|
+
require 'representable/json/hash'
|
3
|
+
|
4
|
+
# Represents a validators hash for a model.
|
5
|
+
module ValidatorsRepresenter
|
6
|
+
class ValidatorClient
|
7
|
+
attr_accessor :kind, :options
|
8
|
+
end
|
9
|
+
|
10
|
+
# Represents a single Validator instance.
|
11
|
+
module ValidatorRepresenter
|
12
|
+
include Roar::Representer::JSON
|
13
|
+
property :kind
|
14
|
+
hash :options
|
15
|
+
end
|
16
|
+
|
17
|
+
# Represents an array of validators for an attribute.
|
18
|
+
module AttributeValidators
|
19
|
+
include Representable::JSON::Collection
|
20
|
+
items :extend => ValidatorRepresenter, :class => ValidatorClient
|
21
|
+
end
|
22
|
+
|
23
|
+
include Representable::JSON::Hash
|
24
|
+
values :extend => AttributeValidators, :class => Array
|
25
|
+
end
|
data/lib/roar/rails/version.rb
CHANGED
data/roar-rails.gemspec
CHANGED
@@ -18,7 +18,7 @@ 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.9.
|
21
|
+
s.add_runtime_dependency "roar", "~> 0.9.2"
|
22
22
|
s.add_runtime_dependency "test_xml"
|
23
23
|
s.add_runtime_dependency "actionpack", "~> 3.0"
|
24
24
|
s.add_runtime_dependency "railties", "~> 3.0"
|
data/test/representer_test.rb
CHANGED
@@ -2,12 +2,26 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class RepresenterTest < ActionController::TestCase
|
4
4
|
include Roar::Rails::TestCase
|
5
|
-
|
5
|
+
|
6
6
|
tests SingersController
|
7
|
-
|
7
|
+
|
8
8
|
test "representers can use URL helpers" do
|
9
9
|
get :show, :id => "bumi"
|
10
10
|
assert_body "{\"name\":\"Bumi\",\"links\":[{\"rel\":\"self\",\"href\":\"http://http://roar.apotomo.de/singers/Bumi\"}]}"
|
11
|
+
end
|
11
12
|
|
13
|
+
test "it works with uninitialized config.representer.default_url_options" do
|
14
|
+
url_options = Rails.application.config.representer.default_url_options
|
15
|
+
|
16
|
+
begin
|
17
|
+
Rails.application.config.representer.default_url_options = nil
|
18
|
+
assert_raises RuntimeError, ArgumentError do
|
19
|
+
get :show, :id => "bumi"
|
20
|
+
end
|
21
|
+
assert $!.message =~ /Missing host to link to/
|
22
|
+
rescue
|
23
|
+
ensure
|
24
|
+
Rails.application.config.representer.default_url_options = url_options
|
25
|
+
end
|
12
26
|
end
|
13
27
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
Singer = Struct.new(:name)
|
4
|
+
class SingersController < ActionController::Base
|
5
|
+
respond_to :json
|
6
|
+
|
7
|
+
def explicit_representer
|
8
|
+
singer = Musician.new("Bumi")
|
9
|
+
respond_with singer, :with_representer => SingerRepresenter
|
10
|
+
end
|
11
|
+
|
12
|
+
def implicit_representer
|
13
|
+
singer = Singer.new("Bumi")
|
14
|
+
respond_with singer
|
15
|
+
end
|
16
|
+
|
17
|
+
def collection_of_representers
|
18
|
+
singers = [Singer.new("Bumi"), Singer.new("Bjork"), Singer.new("Sinead")]
|
19
|
+
respond_with singers
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.responder
|
23
|
+
Class.new(super).send :include, Roar::Rails::Responder
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class ResponderTest < ActionController::TestCase
|
29
|
+
include Roar::Rails::TestCase
|
30
|
+
|
31
|
+
tests SingersController
|
32
|
+
|
33
|
+
test "responder allows specifying representer" do
|
34
|
+
get :explicit_representer, :format => 'json'
|
35
|
+
assert_equal singer.to_json, @response.body
|
36
|
+
end
|
37
|
+
|
38
|
+
test "responder finds representer by convention" do
|
39
|
+
get :implicit_representer, :format => 'json'
|
40
|
+
assert_equal singer.to_json, @response.body
|
41
|
+
end
|
42
|
+
|
43
|
+
test "responder works with collections" do
|
44
|
+
get :collection_of_representers, :format => 'json'
|
45
|
+
assert_equal singers.map(&:to_hash).to_json, @response.body
|
46
|
+
end
|
47
|
+
|
48
|
+
def singer(name="Bumi")
|
49
|
+
singer = Musician.new(name)
|
50
|
+
singer.extend SingerRepresenter
|
51
|
+
end
|
52
|
+
|
53
|
+
def singers
|
54
|
+
[singer("Bumi"), singer("Bjork"), singer("Sinead")]
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'active_model'
|
3
|
+
require 'roar/rails/validations_representer'
|
4
|
+
|
5
|
+
|
6
|
+
class ValidationsTest < MiniTest::Spec
|
7
|
+
class Comment
|
8
|
+
include ActiveModel::Validations
|
9
|
+
validates :name, :presence => true
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "ValidatorRepresenter" do
|
13
|
+
it "renders a representation in #to_json" do
|
14
|
+
assert_equal "{\"kind\":\"presence\",\"options\":{}}", Comment._validators[:name].first.extend(ValidatorsRepresenter::ValidatorRepresenter).to_json
|
15
|
+
end
|
16
|
+
|
17
|
+
it "parses validator config in #from_json" do
|
18
|
+
validator = ValidatorsRepresenter::ValidatorClient.new.extend(ValidatorsRepresenter::ValidatorRepresenter).from_json("{\"kind\":\"presence\",\"attributes\":[\"name\"],\"options\":{}}")
|
19
|
+
assert_equal "presence", validator.kind
|
20
|
+
assert_equal({}, validator.options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "ValidatorsRepresenter" do
|
25
|
+
it "renders a collection in #to_json" do
|
26
|
+
assert_equal "{\"name\":[{\"kind\":\"presence\",\"options\":{}}]}", Comment._validators.extend(ValidatorsRepresenter).to_json
|
27
|
+
end
|
28
|
+
|
29
|
+
it "parses validators in #from_json" do
|
30
|
+
validations = {}.extend(ValidatorsRepresenter).from_json("{\"name\":[{\"kind\":\"presence\",\"options\":[]}]}")
|
31
|
+
assert_equal "presence", validations["name"].first.kind
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Nick Sutterer
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-
|
17
|
+
date: 2012-02-17 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -28,8 +28,8 @@ dependencies:
|
|
28
28
|
segments:
|
29
29
|
- 0
|
30
30
|
- 9
|
31
|
-
-
|
32
|
-
version: 0.9.
|
31
|
+
- 2
|
32
|
+
version: 0.9.2
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
@@ -112,13 +112,18 @@ extra_rdoc_files: []
|
|
112
112
|
|
113
113
|
files:
|
114
114
|
- .gitignore
|
115
|
+
- .travis.yml
|
116
|
+
- CHANGES.markdown
|
115
117
|
- Gemfile
|
116
118
|
- README.markdown
|
117
119
|
- Rakefile
|
120
|
+
- gemfiles/Gemfile.rails3-0
|
118
121
|
- lib/roar-rails.rb
|
119
122
|
- lib/roar/rails/railtie.rb
|
123
|
+
- lib/roar/rails/responder.rb
|
120
124
|
- lib/roar/rails/test_case.rb
|
121
125
|
- lib/roar/rails/url_methods.rb
|
126
|
+
- lib/roar/rails/validations_representer.rb
|
122
127
|
- lib/roar/rails/version.rb
|
123
128
|
- roar-rails.gemspec
|
124
129
|
- test/dummy/Rakefile
|
@@ -156,8 +161,10 @@ files:
|
|
156
161
|
- test/dummy/tmp/app/cells/blog/post/latest.html.erb
|
157
162
|
- test/dummy/tmp/app/cells/blog/post_cell.rb
|
158
163
|
- test/representer_test.rb
|
164
|
+
- test/responder_test.rb
|
159
165
|
- test/test_case_test.rb
|
160
166
|
- test/test_helper.rb
|
167
|
+
- test/validations_test.rb
|
161
168
|
has_rdoc: true
|
162
169
|
homepage: ""
|
163
170
|
licenses: []
|