acts_as_api 0.1.10 → 0.2.1
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.
- data/History.txt +9 -0
- data/README.rdoc +97 -11
- data/Rakefile +1 -1
- data/lib/acts_as_api.rb +4 -4
- data/lib/acts_as_api/array.rb +2 -2
- data/lib/acts_as_api/base.rb +12 -10
- data/lib/acts_as_api/rendering.rb +8 -5
- metadata +19 -8
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 0.2.1 2010-09-20
|
2
|
+
|
3
|
+
* Updated to work with Rails 3.0.0
|
4
|
+
|
5
|
+
* Added support for multiple renderings of the same model (e.g. useful for versioning).
|
6
|
+
Note that the interface of acts as api changed, soyou have to update your code.
|
7
|
+
|
8
|
+
* Updated dependecies to user Rails 3.0.0 libs instead of beta.
|
9
|
+
|
1
10
|
=== 0.1.10 2010-07-23
|
2
11
|
|
3
12
|
* More Bugfixes. When you want to render an Array of records (e.g. from MyRecord.all)
|
data/README.rdoc
CHANGED
@@ -19,6 +19,12 @@ acts_as_api uses the *default Rails serializers* for XML and JSON, so you don't
|
|
19
19
|
mess around with even more dependencies. Once you change the serializers for your Rails app,
|
20
20
|
they will be changed for acts_as_api too.
|
21
21
|
|
22
|
+
As of the version 0.2.0 it supports multiple api rendering templates for a models.
|
23
|
+
This is especially useful for API versioning or for example for private vs. public
|
24
|
+
access points to a user's profile.
|
25
|
+
|
26
|
+
*Note that upgrading to 0.2.0 will break code that worked with previous versions as you now have to specify an API template*
|
27
|
+
|
22
28
|
== SYNOPSIS:
|
23
29
|
|
24
30
|
=== Set up your model
|
@@ -37,10 +43,13 @@ via the api, you would do something like this:
|
|
37
43
|
acts_as_api
|
38
44
|
|
39
45
|
# define the accessible attributes/methods for the api response
|
40
|
-
api_accessible :firstname, :lastname
|
46
|
+
api_accessible :default => [ :firstname, :lastname ]
|
41
47
|
|
42
48
|
end
|
43
49
|
|
50
|
+
|
51
|
+
An API template with the name +:default+ was created, see below how to use it in the controller:
|
52
|
+
|
44
53
|
=== Set up controller
|
45
54
|
|
46
55
|
Now you just have to exchange the +render+ method in your controller for the +render_for_api+ method.
|
@@ -52,13 +61,14 @@ Now you just have to exchange the +render+ method in your controller for the +re
|
|
52
61
|
|
53
62
|
respond_to do |format|
|
54
63
|
format.html # show.html.erb
|
55
|
-
format.xml { render_for_api :xml => @customer }
|
56
|
-
format.json { render_for_api :json => @customer }
|
64
|
+
format.xml { render_for_api :default, :xml => @customer }
|
65
|
+
format.json { render_for_api :default, :json => @customer }
|
57
66
|
end
|
58
67
|
end
|
59
68
|
|
60
69
|
end
|
61
70
|
|
71
|
+
|
62
72
|
=== That's it!
|
63
73
|
|
64
74
|
Try it. The response should now look like this:
|
@@ -72,6 +82,80 @@ Try it. The response should now look like this:
|
|
72
82
|
Other attributes of the model like +created_at+ or +updated_at+ won't be included because they were
|
73
83
|
not listed by +api_accessible+ in the model.
|
74
84
|
|
85
|
+
== But you can do more...
|
86
|
+
|
87
|
+
=== API Versioning
|
88
|
+
|
89
|
+
With the different named API templates, API versioning is pretty easy:
|
90
|
+
|
91
|
+
class User < ActiveRecord::Base
|
92
|
+
|
93
|
+
# let this model act as api!
|
94
|
+
acts_as_api
|
95
|
+
|
96
|
+
# define the accessible attributes/methods for the api response
|
97
|
+
api_accessible
|
98
|
+
:v1_public => [ :firstname, :age ],
|
99
|
+
:v2_public => [ :firstname, :age, :sex ],
|
100
|
+
|
101
|
+
:v1_private => [ :firstname, :lastname, :age, :sex ],
|
102
|
+
:v2_private => [ :firstname, :lastname, :age, :sex, :phone ]
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
Now you could create a method in the application controller of your app:
|
107
|
+
|
108
|
+
def api_template(version = :v2, template = :public)
|
109
|
+
"#{version.to_s}_#{template.to_s}".to_sym
|
110
|
+
end
|
111
|
+
|
112
|
+
And render the API responses:
|
113
|
+
|
114
|
+
class UsersController < ApplicationController
|
115
|
+
|
116
|
+
# renders the :v2_public template
|
117
|
+
def show
|
118
|
+
@user = User.find(params[:id])
|
119
|
+
|
120
|
+
respond_to do |format|
|
121
|
+
format.html # show.html.erb
|
122
|
+
format.xml { render_for_api api_template, :xml => @user }
|
123
|
+
format.json { render_for_api api_template, :json => @user }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# renders the :v1_private template
|
128
|
+
def profile_deprecated
|
129
|
+
@user = @current_user
|
130
|
+
|
131
|
+
respond_to do |format|
|
132
|
+
format.html # show.html.erb
|
133
|
+
format.xml { render_for_api api_template(:v1, :private), :xml => @user }
|
134
|
+
format.json { render_for_api api_template(:v1, :private), :json => @user }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
=== Metadata
|
142
|
+
|
143
|
+
You can include metadata elements in the response outside of your objects and collections. Typical usage for this is to include a total results count or page. Just pass in a :meta key with a hash of the meta items you want.
|
144
|
+
|
145
|
+
class CustomersController < ApplicationController
|
146
|
+
|
147
|
+
def index
|
148
|
+
@customers = Customer.paginate(:all, :page = params[:page])
|
149
|
+
metadata = { :total => @customers.total_entries, :page => params[:page] }
|
150
|
+
respond_to do |format|
|
151
|
+
format.html # show.html.erb
|
152
|
+
format.xml { render_for_api :default, :xml => @customer, :meta => metadata }
|
153
|
+
format.json { render_for_api :default, :json => @customer, :meta => metadata }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
75
159
|
=== What can I include in my responses?
|
76
160
|
|
77
161
|
You can do basically anything:
|
@@ -95,19 +179,20 @@ The model +Customer+ shows all kinds of ways to add data to your API response.
|
|
95
179
|
|
96
180
|
# define the accessible attributes/methods for the api response
|
97
181
|
# some attributes of the model
|
98
|
-
api_accessible :firstname, :lastname, :age,
|
182
|
+
api_accessible :default => [ :firstname, :lastname, :age,
|
99
183
|
# you can include methods
|
100
184
|
:full_name,
|
101
185
|
# include associated model in response
|
102
186
|
:orders,
|
103
187
|
# rename the node for orders
|
104
|
-
:renamed_orders => :orders,
|
188
|
+
{ :renamed_orders => :orders },
|
105
189
|
# put orders in another subnode
|
106
|
-
:subnode_orders => { :sub_oders => :orders },
|
190
|
+
{ :subnode_orders => { :sub_oders => :orders } },
|
107
191
|
# rename nodes/tag names
|
108
|
-
:other_node => :say_something,
|
192
|
+
{ :other_node => :say_something },
|
109
193
|
# create a deeper node hierarchy
|
110
|
-
:maybe => { :useful => { :for => :say_something } }
|
194
|
+
{ :maybe => { :useful => { :for => :say_something } } }
|
195
|
+
]
|
111
196
|
|
112
197
|
# some example methods
|
113
198
|
def full_name
|
@@ -131,9 +216,10 @@ The model +Order+ also acts as api and is even able to access a method of their
|
|
131
216
|
|
132
217
|
# define the accessible attributes/methods for the api response
|
133
218
|
# some attributes of the model
|
134
|
-
api_accessible :city, :amount,
|
219
|
+
api_accessible :default => [ :city, :amount,
|
135
220
|
#access a method of the parent association
|
136
|
-
:parent_name => "customer.full_name"
|
221
|
+
{ :parent_name => "customer.full_name" }
|
222
|
+
]
|
137
223
|
|
138
224
|
end
|
139
225
|
|
@@ -145,7 +231,7 @@ If you want a working example right out of the box, grab the example app: http:/
|
|
145
231
|
|
146
232
|
== REQUIREMENTS:
|
147
233
|
|
148
|
-
* Rails 3
|
234
|
+
* Rails 3.0.0
|
149
235
|
|
150
236
|
== INSTALL:
|
151
237
|
|
data/Rakefile
CHANGED
@@ -14,7 +14,7 @@ $hoe = Hoe.spec 'acts_as_api' do
|
|
14
14
|
self.developer 'Christian Bäuerlein', 'christian@ffwdme.com'
|
15
15
|
#self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
16
16
|
#self.rubyforge_name = self.name # TODO this is default value
|
17
|
-
self.extra_deps = [['activerecord','>= 3.0.0
|
17
|
+
self.extra_deps = [['activerecord','>= 3.0.0'], ['actionpack','>= 3.0.0']]
|
18
18
|
|
19
19
|
end
|
20
20
|
|
data/lib/acts_as_api.rb
CHANGED
@@ -16,7 +16,7 @@ require "acts_as_api/array"
|
|
16
16
|
# acts_as_api uses the default serializers of your rails app and doesn't
|
17
17
|
# force you into more dependencies.
|
18
18
|
module ActsAsApi
|
19
|
-
VERSION = '0.1
|
19
|
+
VERSION = '0.2.1'
|
20
20
|
|
21
21
|
# The accepted response formats
|
22
22
|
# Default is +[:xml, :json]+
|
@@ -43,7 +43,7 @@ if defined?(ActiveRecord::Base)
|
|
43
43
|
ActiveRecord::Base.extend ActsAsApi::Base
|
44
44
|
end
|
45
45
|
|
46
|
-
# Attach ourselves to the
|
47
|
-
if defined?(
|
48
|
-
|
46
|
+
# Attach ourselves to the action controller of rails
|
47
|
+
if defined?(ActionController::Base)
|
48
|
+
ActionController::Base.send :include, ActsAsApi::Rendering
|
49
49
|
end
|
data/lib/acts_as_api/array.rb
CHANGED
@@ -6,13 +6,13 @@ class Array
|
|
6
6
|
# The Array checks all its items if they respond to the +as_api_response+ method.
|
7
7
|
# If they do, the result of this method will be collected.
|
8
8
|
# If they don't, the item itself will be collected.
|
9
|
-
def as_api_response
|
9
|
+
def as_api_response(api_template)
|
10
10
|
|
11
11
|
sub_items = []
|
12
12
|
|
13
13
|
each do |item|
|
14
14
|
if item.respond_to?(:as_api_response)
|
15
|
-
sub_items << item.as_api_response
|
15
|
+
sub_items << item.as_api_response(api_template)
|
16
16
|
else
|
17
17
|
sub_items << item
|
18
18
|
end
|
data/lib/acts_as_api/base.rb
CHANGED
@@ -28,13 +28,15 @@ module ActsAsApi
|
|
28
28
|
# *Note*: There is only whitelisting for api accessible attributes.
|
29
29
|
# So once the model acts as api, you have to determine all attributes here that should
|
30
30
|
# be contained in the api responses.
|
31
|
-
def api_accessible(
|
32
|
-
|
31
|
+
def api_accessible(api_templates)
|
32
|
+
api_templates.each do |api_template, attributes|
|
33
|
+
write_inheritable_attribute("api_accessible_#{api_template}".to_sym, Set.new(attributes) + (api_accessible_attributes(api_template) || []))
|
34
|
+
end
|
33
35
|
end
|
34
36
|
|
35
37
|
# Returns an array of all the attributes that have been made accessible to the api response.
|
36
|
-
def api_accessible_attributes
|
37
|
-
read_inheritable_attribute(
|
38
|
+
def api_accessible_attributes(api_template)
|
39
|
+
read_inheritable_attribute("api_accessible_#{api_template}".to_sym)
|
38
40
|
end
|
39
41
|
|
40
42
|
end
|
@@ -43,8 +45,8 @@ module ActsAsApi
|
|
43
45
|
module InstanceMethods
|
44
46
|
|
45
47
|
# Creates the api response of the model and returns it as a Hash.
|
46
|
-
def as_api_response
|
47
|
-
api_attributes = self.class.api_accessible_attributes
|
48
|
+
def as_api_response(api_template)
|
49
|
+
api_attributes = self.class.api_accessible_attributes(api_template)
|
48
50
|
|
49
51
|
api_output = {}
|
50
52
|
|
@@ -59,7 +61,7 @@ module ActsAsApi
|
|
59
61
|
out = send attribute
|
60
62
|
|
61
63
|
if out.respond_to?(:as_api_response)
|
62
|
-
out = out.send(:as_api_response)
|
64
|
+
out = out.send(:as_api_response, api_template)
|
63
65
|
end
|
64
66
|
|
65
67
|
api_output[attribute] = out
|
@@ -92,7 +94,7 @@ module ActsAsApi
|
|
92
94
|
out = send v
|
93
95
|
|
94
96
|
if out.respond_to?(:as_api_response)
|
95
|
-
out = out.send(:as_api_response)
|
97
|
+
out = out.send(:as_api_response, api_template)
|
96
98
|
end
|
97
99
|
|
98
100
|
leaf[:parent][k] = out
|
@@ -117,13 +119,13 @@ module ActsAsApi
|
|
117
119
|
end
|
118
120
|
|
119
121
|
end
|
120
|
-
|
122
|
+
|
121
123
|
end
|
122
124
|
|
123
125
|
api_output
|
124
126
|
|
125
127
|
end
|
126
|
-
|
128
|
+
|
127
129
|
end
|
128
130
|
|
129
131
|
|
@@ -8,7 +8,7 @@ module ActsAsApi
|
|
8
8
|
# to simply generate API outputs.
|
9
9
|
#
|
10
10
|
# The default Rails serializers are used to serialize the data.
|
11
|
-
def render_for_api(render_options)
|
11
|
+
def render_for_api(api_template, render_options)
|
12
12
|
|
13
13
|
# extract the api format and model
|
14
14
|
api_format_options = {}
|
@@ -20,9 +20,10 @@ module ActsAsApi
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
meta_hash = render_options[:meta] if render_options.has_key?(:meta)
|
23
24
|
|
24
25
|
api_format = api_format_options.keys.first
|
25
|
-
api_model
|
26
|
+
api_model = api_format_options.values.first
|
26
27
|
|
27
28
|
# set the params to render
|
28
29
|
output_params = render_options
|
@@ -57,12 +58,14 @@ module ActsAsApi
|
|
57
58
|
#output_params[:root] = output_params[:root].camelize if render_options.has_key?(:camelize) && render_options[:camelize]
|
58
59
|
#output_params[:root] = output_params[:root].dasherize if !render_options.has_key?(:dasherize) || render_options[:dasherize]
|
59
60
|
|
60
|
-
api_response = api_model.as_api_response
|
61
|
+
api_response = api_model.as_api_response(api_template)
|
61
62
|
|
62
|
-
if ActsAsApi::ADD_ROOT_NODE_FOR.include? api_format
|
63
|
+
if meta_hash or ActsAsApi::ADD_ROOT_NODE_FOR.include? api_format
|
63
64
|
api_response = { api_root_name.to_sym => api_response}
|
64
65
|
end
|
65
66
|
|
67
|
+
api_response = meta_hash.merge api_response if meta_hash
|
68
|
+
|
66
69
|
# create the Hash as response
|
67
70
|
output_params[api_format] = api_response
|
68
71
|
|
@@ -71,5 +74,5 @@ module ActsAsApi
|
|
71
74
|
end
|
72
75
|
|
73
76
|
end
|
74
|
-
|
77
|
+
|
75
78
|
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
8
|
+
- 2
|
7
9
|
- 1
|
8
|
-
|
9
|
-
version: 0.1.10
|
10
|
+
version: 0.2.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- "Christian B\xC3\xA4uerlein"
|
@@ -14,46 +15,50 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-09-21 00:00:00 +02:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: activerecord
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
27
30
|
segments:
|
28
31
|
- 3
|
29
32
|
- 0
|
30
33
|
- 0
|
31
|
-
|
32
|
-
version: 3.0.0.beta4
|
34
|
+
version: 3.0.0
|
33
35
|
type: :runtime
|
34
36
|
version_requirements: *id001
|
35
37
|
- !ruby/object:Gem::Dependency
|
36
38
|
name: actionpack
|
37
39
|
prerelease: false
|
38
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
39
42
|
requirements:
|
40
43
|
- - ">="
|
41
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 7
|
42
46
|
segments:
|
43
47
|
- 3
|
44
48
|
- 0
|
45
49
|
- 0
|
46
|
-
|
47
|
-
version: 3.0.0.beta4
|
50
|
+
version: 3.0.0
|
48
51
|
type: :runtime
|
49
52
|
version_requirements: *id002
|
50
53
|
- !ruby/object:Gem::Dependency
|
51
54
|
name: rubyforge
|
52
55
|
prerelease: false
|
53
56
|
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
54
58
|
requirements:
|
55
59
|
- - ">="
|
56
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 7
|
57
62
|
segments:
|
58
63
|
- 2
|
59
64
|
- 0
|
@@ -65,9 +70,11 @@ dependencies:
|
|
65
70
|
name: hoe
|
66
71
|
prerelease: false
|
67
72
|
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
68
74
|
requirements:
|
69
75
|
- - ">="
|
70
76
|
- !ruby/object:Gem::Version
|
77
|
+
hash: 21
|
71
78
|
segments:
|
72
79
|
- 2
|
73
80
|
- 6
|
@@ -112,23 +119,27 @@ rdoc_options:
|
|
112
119
|
require_paths:
|
113
120
|
- lib
|
114
121
|
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
115
123
|
requirements:
|
116
124
|
- - ">="
|
117
125
|
- !ruby/object:Gem::Version
|
126
|
+
hash: 3
|
118
127
|
segments:
|
119
128
|
- 0
|
120
129
|
version: "0"
|
121
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
122
132
|
requirements:
|
123
133
|
- - ">="
|
124
134
|
- !ruby/object:Gem::Version
|
135
|
+
hash: 3
|
125
136
|
segments:
|
126
137
|
- 0
|
127
138
|
version: "0"
|
128
139
|
requirements: []
|
129
140
|
|
130
141
|
rubyforge_project: acts_as_api
|
131
|
-
rubygems_version: 1.3.
|
142
|
+
rubygems_version: 1.3.7
|
132
143
|
signing_key:
|
133
144
|
specification_version: 3
|
134
145
|
summary: acts_as_api makes creating XML/JSON responses in Rails 3 easy and fun.
|