acts_as_api 0.3.3 → 0.3.4
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 +4 -0
- data/lib/acts_as_api.rb +1 -0
- data/lib/acts_as_api/api_template.rb +70 -55
- data/lib/acts_as_api/base.rb +1 -1
- data/lib/acts_as_api/exceptions.rb +4 -0
- data/lib/acts_as_api/version.rb +1 -1
- data/spec/models/base/extending_spec.rb +51 -0
- data/spec/models/base/undefined_spec.rb +1 -1
- metadata +5 -4
data/History.txt
CHANGED
data/lib/acts_as_api.rb
CHANGED
@@ -2,15 +2,17 @@ module ActsAsApi
|
|
2
2
|
# Represents an api template for a model.
|
3
3
|
# This class should not be initiated by yourself, api templates
|
4
4
|
# are created by defining them in the model by calling: +api_accessible+.
|
5
|
-
#
|
5
|
+
#
|
6
6
|
# The api template is configured in the block passed to +api_accessible+.
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# Please note that +ApiTemplate+ inherits from +Hash+ so you can use all
|
9
9
|
# kind of +Hash+ and +Enumerable+ methods to manipulate the template.
|
10
10
|
class ApiTemplate < Hash
|
11
11
|
|
12
12
|
# The name of the api template as a Symbol.
|
13
13
|
attr_accessor :api_template
|
14
|
+
|
15
|
+
attr_reader :options
|
14
16
|
|
15
17
|
# Returns a new ApiTemplate with the api template name
|
16
18
|
# set to the passed template.
|
@@ -20,7 +22,16 @@ module ActsAsApi
|
|
20
22
|
return t
|
21
23
|
end
|
22
24
|
|
23
|
-
|
25
|
+
def initialize
|
26
|
+
@options ||= {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def merge!(other_hash, &block)
|
30
|
+
super
|
31
|
+
self.options.merge!(other_hash.options) if other_hash.respond_to?(:options)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Adds a field to the api template
|
24
35
|
#
|
25
36
|
# The value passed can be one of the following:
|
26
37
|
# * Symbol - the method with the same name will be called on the model when rendering.
|
@@ -35,42 +46,43 @@ module ActsAsApi
|
|
35
46
|
|
36
47
|
self[item_key] = val
|
37
48
|
|
38
|
-
@options ||= {}
|
39
49
|
@options[item_key] = options
|
40
50
|
end
|
41
51
|
|
42
|
-
# Removes
|
43
|
-
def remove(
|
44
|
-
self.delete(
|
52
|
+
# Removes a field from the template
|
53
|
+
def remove(field)
|
54
|
+
self.delete(field)
|
45
55
|
end
|
46
56
|
|
47
|
-
# Returns the options of
|
48
|
-
def options_for(
|
49
|
-
@options[
|
57
|
+
# Returns the options of a field in the api template
|
58
|
+
def options_for(field)
|
59
|
+
@options[field]
|
50
60
|
end
|
51
61
|
|
52
|
-
# Returns the passed option of
|
53
|
-
def option_for(
|
54
|
-
@options[
|
62
|
+
# Returns the passed option of a field in the api template
|
63
|
+
def option_for(field, option)
|
64
|
+
@options[field][option] if @options[field]
|
55
65
|
end
|
56
|
-
|
66
|
+
|
57
67
|
# If a special template name for the passed item is specified
|
58
68
|
# it will be returned, if not the original api template.
|
59
|
-
def api_template_for(
|
60
|
-
return api_template unless
|
61
|
-
|
69
|
+
def api_template_for(fieldset, field)
|
70
|
+
return api_template unless fieldset.is_a? ActsAsApi::ApiTemplate
|
71
|
+
fieldset.option_for(field, :template) || api_template
|
62
72
|
end
|
63
|
-
|
73
|
+
|
64
74
|
# Decides if the passed item should be added to
|
65
|
-
# the response.
|
66
|
-
def allowed_to_render?(
|
67
|
-
return true unless
|
75
|
+
# the response based on the conditional options passed.
|
76
|
+
def allowed_to_render?(fieldset, field, model)
|
77
|
+
return true unless fieldset.is_a? ActsAsApi::ApiTemplate
|
68
78
|
allowed = true
|
69
|
-
allowed = condition_fulfilled?(model,
|
70
|
-
allowed = !(condition_fulfilled?(model,
|
79
|
+
allowed = condition_fulfilled?(model, fieldset.option_for(field, :if)) if fieldset.option_for(field, :if)
|
80
|
+
allowed = !(condition_fulfilled?(model, fieldset.option_for(field, :unless))) if fieldset.option_for(field, :unless)
|
71
81
|
return allowed
|
72
82
|
end
|
73
|
-
|
83
|
+
|
84
|
+
# Checks if a condition is fulfilled
|
85
|
+
# (result is not nil or false)
|
74
86
|
def condition_fulfilled?(model, condition)
|
75
87
|
case condition
|
76
88
|
when Symbol
|
@@ -86,48 +98,51 @@ module ActsAsApi
|
|
86
98
|
def to_response_hash(model)
|
87
99
|
queue = []
|
88
100
|
api_output = {}
|
89
|
-
|
101
|
+
|
102
|
+
queue << { :output => api_output, :item => self }
|
90
103
|
|
91
104
|
until queue.empty? do
|
92
|
-
|
93
|
-
|
94
|
-
|
105
|
+
leaf = queue.pop
|
106
|
+
fieldset = leaf[:item]
|
107
|
+
|
108
|
+
fieldset.each do |field, value|
|
95
109
|
|
96
|
-
|
110
|
+
next unless allowed_to_render?(fieldset, field, model)
|
97
111
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
when Proc
|
105
|
-
out = v.call(model)
|
112
|
+
case value
|
113
|
+
when Symbol
|
114
|
+
if model.respond_to?(value)
|
115
|
+
out = model.send value
|
116
|
+
end
|
106
117
|
|
107
|
-
|
108
|
-
|
109
|
-
out = model
|
110
|
-
v.split(".").each do |method|
|
111
|
-
out = out.send(method.to_sym)
|
112
|
-
end
|
118
|
+
when Proc
|
119
|
+
out = value.call(model)
|
113
120
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
121
|
+
when String
|
122
|
+
# go up the call chain
|
123
|
+
out = model
|
124
|
+
value.split(".").each do |method|
|
125
|
+
out = out.send(method.to_sym)
|
118
126
|
end
|
119
127
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
128
|
+
when Hash
|
129
|
+
leaf[:output][field] ||= {}
|
130
|
+
queue << { :output => leaf[:output][field], :item => value }
|
131
|
+
next
|
132
|
+
end
|
124
133
|
|
125
|
-
|
134
|
+
if out.respond_to?(:as_api_response)
|
135
|
+
sub_template = api_template_for(fieldset, field)
|
136
|
+
out = out.send(:as_api_response, sub_template)
|
126
137
|
end
|
127
|
-
end
|
128
138
|
|
129
|
-
|
139
|
+
leaf[:output][field] = out
|
140
|
+
end
|
141
|
+
|
130
142
|
end
|
131
|
-
|
143
|
+
|
144
|
+
api_output
|
132
145
|
end
|
146
|
+
|
133
147
|
end
|
148
|
+
end
|
data/lib/acts_as_api/base.rb
CHANGED
@@ -58,7 +58,7 @@ module ActsAsApi
|
|
58
58
|
def as_api_response(api_template)
|
59
59
|
api_attributes = self.class.api_accessible_attributes(api_template)
|
60
60
|
|
61
|
-
raise "acts_as_api template :#{api_template.to_s} was not found for model #{self.class}" if api_attributes.nil?
|
61
|
+
raise ActsAsApi::TemplateNotFoundError.new("acts_as_api template :#{api_template.to_s} was not found for model #{self.class}") if api_attributes.nil?
|
62
62
|
|
63
63
|
api_attributes.to_response_hash(self)
|
64
64
|
end
|
data/lib/acts_as_api/version.rb
CHANGED
@@ -70,5 +70,56 @@ describe ActsAsApi::Base do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
end
|
73
|
+
|
74
|
+
describe "and inherit a field using another template name", :meow => true do
|
75
|
+
|
76
|
+
before(:each) do
|
77
|
+
Task.acts_as_api
|
78
|
+
Task.api_accessible :other_template do |t|
|
79
|
+
t.add :description
|
80
|
+
t.add :time_spent
|
81
|
+
end
|
82
|
+
User.api_accessible :extending_other_template, :extend => :other_sub_template
|
83
|
+
@response = @luke.as_api_response(:extending_other_template)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "returns a hash" do
|
87
|
+
@response.should be_kind_of(Hash)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns the correct number of fields" do
|
91
|
+
@response.should have(2).keys
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns all specified fields" do
|
95
|
+
@response.keys.should include(:first_name)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "returns the correct values for the specified fields" do
|
99
|
+
@response.values.should include(@luke.first_name)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns all specified fields" do
|
103
|
+
@response.keys.should include(:tasks)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns the correct values for the specified fields" do
|
107
|
+
@response[:tasks].should be_an Array
|
108
|
+
@response[:tasks].should have(3).tasks
|
109
|
+
end
|
110
|
+
|
111
|
+
it "contains the associated child models with the determined api template" do
|
112
|
+
@response[:tasks].each do |task|
|
113
|
+
task.keys.should include(:description, :time_spent)
|
114
|
+
task.keys.should have(2).attributes
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "contains the correct data of the child models" do
|
119
|
+
task_hash = [ @destroy_deathstar, @study_with_yoda, @win_rebellion ].collect{|t| { :description => t.description, :time_spent => t.time_spent } }
|
120
|
+
@response[:tasks].should eql task_hash
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
73
124
|
end
|
74
125
|
end
|
@@ -13,7 +13,7 @@ describe ActsAsApi::Base do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
it "raises an descriptive error" do
|
16
|
-
lambda{ @luke.as_api_response(:does_not_exist) }.should raise_error(
|
16
|
+
lambda{ @luke.as_api_response(:does_not_exist) }.should raise_error(ActsAsApi::TemplateNotFoundError)
|
17
17
|
end
|
18
18
|
|
19
19
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 4
|
10
|
+
version: 0.3.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Christian B\xC3\xA4uerlein"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-04-
|
18
|
+
date: 2011-04-26 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- lib/acts_as_api/array.rb
|
108
108
|
- lib/acts_as_api/base.rb
|
109
109
|
- lib/acts_as_api/config.rb
|
110
|
+
- lib/acts_as_api/exceptions.rb
|
110
111
|
- lib/acts_as_api/rails_renderer.rb
|
111
112
|
- lib/acts_as_api/rendering.rb
|
112
113
|
- lib/acts_as_api/version.rb
|