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.
@@ -1,3 +1,7 @@
1
+ === 0.3.4 2011-04-26
2
+
3
+ * Fixed a bug concerning the inheritance of sub templates/additional options
4
+
1
5
  === 0.3.3 2011-04-24
2
6
 
3
7
  * Added support for :if and :unless options
@@ -6,6 +6,7 @@ $:.unshift(File.dirname(__FILE__)) unless
6
6
 
7
7
  require "acts_as_api/array"
8
8
  require "acts_as_api/rails_renderer"
9
+ require "acts_as_api/exceptions"
9
10
 
10
11
  # acts_as_api is a gem that aims to make the construction of JSON and XML
11
12
  # responses in rails 3 easy and fun.
@@ -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
- # Adds an item to the api template
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 an item from the template
43
- def remove(item)
44
- self.delete(item)
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 an item in the api template
48
- def options_for(item)
49
- @options[item]
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 an item in the api template
53
- def option_for(item, option)
54
- @options[item][option] if @options[item]
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(parent, item)
60
- return api_template unless parent.is_a? ActsAsApi::ApiTemplate
61
- parent.option_for(item, :template) || api_template
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?(parent, item, model)
67
- return true unless parent.is_a? ActsAsApi::ApiTemplate
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, parent.option_for(item, :if)) if parent.option_for(item, :if)
70
- allowed = !(condition_fulfilled?(model, parent.option_for(item, :unless))) if parent.option_for(item, :unless)
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
- queue << { :parent => api_output, :item => self }
101
+
102
+ queue << { :output => api_output, :item => self }
90
103
 
91
104
  until queue.empty? do
92
- leaf = queue.pop
93
-
94
- leaf[:item].each do |k,v|
105
+ leaf = queue.pop
106
+ fieldset = leaf[:item]
107
+
108
+ fieldset.each do |field, value|
95
109
 
96
- next unless allowed_to_render?(leaf[:item], k, model)
110
+ next unless allowed_to_render?(fieldset, field, model)
97
111
 
98
- case v
99
- when Symbol
100
- if model.respond_to?(v)
101
- out = model.send v
102
- end
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
- when String
108
- # go up the call chain
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
- when Hash
115
- leaf[:parent][k] ||= {}
116
- queue << { :parent => leaf[:parent][k], :item => v}
117
- next
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
- if out.respond_to?(:as_api_response)
121
- sub_template = api_template_for(leaf[:item], k)
122
- out = out.send(:as_api_response, sub_template)
123
- end
128
+ when Hash
129
+ leaf[:output][field] ||= {}
130
+ queue << { :output => leaf[:output][field], :item => value }
131
+ next
132
+ end
124
133
 
125
- leaf[:parent][k] = out
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
- api_output
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
@@ -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
@@ -0,0 +1,4 @@
1
+ module ActsAsApi
2
+ class ActsAsApiError < RuntimeError; end
3
+ class TemplateNotFoundError < ActsAsApiError; end
4
+ end
@@ -1,3 +1,3 @@
1
1
  module ActsAsApi
2
- VERSION = "0.3.3"
2
+ VERSION = "0.3.4"
3
3
  end
@@ -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(RuntimeError)
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: 21
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 3
10
- version: 0.3.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-24 00:00:00 +02:00
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