acts_as_api_sequel 0.0.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.
Files changed (206) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +13 -0
  5. data/History.txt +108 -0
  6. data/README.md +126 -0
  7. data/Rakefile +48 -0
  8. data/acts_as_api.gemspec +28 -0
  9. data/examples/introduction/docco.css +186 -0
  10. data/examples/introduction/index.html +338 -0
  11. data/examples/introduction/index.rb +144 -0
  12. data/examples/introduction/layout.mustache +67 -0
  13. data/lib/acts_as_api.rb +46 -0
  14. data/lib/acts_as_api/adapters.rb +5 -0
  15. data/lib/acts_as_api/adapters/mongoid.rb +11 -0
  16. data/lib/acts_as_api/api_template.rb +139 -0
  17. data/lib/acts_as_api/array.rb +21 -0
  18. data/lib/acts_as_api/base.rb +88 -0
  19. data/lib/acts_as_api/config.rb +58 -0
  20. data/lib/acts_as_api/exceptions.rb +4 -0
  21. data/lib/acts_as_api/rails_renderer.rb +17 -0
  22. data/lib/acts_as_api/rendering.rb +95 -0
  23. data/lib/acts_as_api/responder.rb +39 -0
  24. data/lib/acts_as_api/version.rb +3 -0
  25. data/spec/README.md +55 -0
  26. data/spec/active_record_dummy/.gitignore +15 -0
  27. data/spec/active_record_dummy/Gemfile +16 -0
  28. data/spec/active_record_dummy/README.rdoc +261 -0
  29. data/spec/active_record_dummy/Rakefile +7 -0
  30. data/spec/active_record_dummy/app/assets/images/rails.png +0 -0
  31. data/spec/active_record_dummy/app/assets/javascripts/application.js +15 -0
  32. data/spec/active_record_dummy/app/assets/stylesheets/application.css +13 -0
  33. data/spec/active_record_dummy/app/controllers/application_controller.rb +3 -0
  34. data/spec/active_record_dummy/app/helpers/application_helper.rb +2 -0
  35. data/spec/active_record_dummy/app/mailers/.gitkeep +0 -0
  36. data/spec/active_record_dummy/app/models/.gitkeep +0 -0
  37. data/spec/active_record_dummy/app/models/profile.rb +4 -0
  38. data/spec/active_record_dummy/app/models/task.rb +4 -0
  39. data/spec/active_record_dummy/app/models/untouched.rb +2 -0
  40. data/spec/active_record_dummy/app/models/user.rb +186 -0
  41. data/spec/active_record_dummy/app/views/layouts/application.html.erb +14 -0
  42. data/spec/active_record_dummy/config.ru +4 -0
  43. data/spec/active_record_dummy/config/application.rb +59 -0
  44. data/spec/active_record_dummy/config/boot.rb +6 -0
  45. data/spec/active_record_dummy/config/database.yml +25 -0
  46. data/spec/active_record_dummy/config/environment.rb +5 -0
  47. data/spec/active_record_dummy/config/environments/development.rb +37 -0
  48. data/spec/active_record_dummy/config/environments/production.rb +67 -0
  49. data/spec/active_record_dummy/config/environments/test.rb +37 -0
  50. data/spec/active_record_dummy/config/initializers/backtrace_silencers.rb +7 -0
  51. data/spec/active_record_dummy/config/initializers/generators.rb +2 -0
  52. data/spec/active_record_dummy/config/initializers/inflections.rb +15 -0
  53. data/spec/active_record_dummy/config/initializers/mime_types.rb +5 -0
  54. data/spec/active_record_dummy/config/initializers/secret_token.rb +7 -0
  55. data/spec/active_record_dummy/config/initializers/session_store.rb +8 -0
  56. data/spec/active_record_dummy/config/initializers/wrap_parameters.rb +14 -0
  57. data/spec/active_record_dummy/config/locales/en.yml +5 -0
  58. data/spec/active_record_dummy/config/routes.rb +59 -0
  59. data/spec/active_record_dummy/db/migrate/20110214201640_create_tables.rb +44 -0
  60. data/spec/active_record_dummy/db/schema.rb +47 -0
  61. data/spec/active_record_dummy/db/seeds.rb +7 -0
  62. data/spec/active_record_dummy/doc/README_FOR_APP +2 -0
  63. data/spec/active_record_dummy/lib/assets/.gitkeep +0 -0
  64. data/spec/active_record_dummy/lib/tasks/.gitkeep +0 -0
  65. data/spec/active_record_dummy/log/.gitkeep +0 -0
  66. data/spec/active_record_dummy/public/404.html +26 -0
  67. data/spec/active_record_dummy/public/422.html +26 -0
  68. data/spec/active_record_dummy/public/500.html +25 -0
  69. data/spec/active_record_dummy/public/favicon.ico +0 -0
  70. data/spec/active_record_dummy/public/index.html +241 -0
  71. data/spec/active_record_dummy/public/robots.txt +5 -0
  72. data/spec/active_record_dummy/script/rails +6 -0
  73. data/spec/active_record_dummy/vendor/assets/javascripts/.gitkeep +0 -0
  74. data/spec/active_record_dummy/vendor/assets/stylesheets/.gitkeep +0 -0
  75. data/spec/active_record_dummy/vendor/plugins/.gitkeep +0 -0
  76. data/spec/controllers/plain_objects_controller_spec.rb +36 -0
  77. data/spec/controllers/respond_with_users_controller_spec.rb +142 -0
  78. data/spec/controllers/users_controller_spec.rb +15 -0
  79. data/spec/models/model_spec.rb +31 -0
  80. data/spec/mongoid_dummy/.gitignore +15 -0
  81. data/spec/mongoid_dummy/Gemfile +18 -0
  82. data/spec/mongoid_dummy/README.rdoc +261 -0
  83. data/spec/mongoid_dummy/Rakefile +7 -0
  84. data/spec/mongoid_dummy/app/assets/images/rails.png +0 -0
  85. data/spec/mongoid_dummy/app/assets/javascripts/application.js +15 -0
  86. data/spec/mongoid_dummy/app/assets/stylesheets/application.css +13 -0
  87. data/spec/mongoid_dummy/app/controllers/application_controller.rb +3 -0
  88. data/spec/mongoid_dummy/app/helpers/application_helper.rb +2 -0
  89. data/spec/mongoid_dummy/app/mailers/.gitkeep +0 -0
  90. data/spec/mongoid_dummy/app/models/.gitkeep +0 -0
  91. data/spec/mongoid_dummy/app/models/profile.rb +10 -0
  92. data/spec/mongoid_dummy/app/models/task.rb +12 -0
  93. data/spec/mongoid_dummy/app/models/untouched.rb +7 -0
  94. data/spec/mongoid_dummy/app/models/user.rb +48 -0
  95. data/spec/mongoid_dummy/app/views/layouts/application.html.erb +14 -0
  96. data/spec/mongoid_dummy/config.ru +4 -0
  97. data/spec/mongoid_dummy/config/application.rb +65 -0
  98. data/spec/mongoid_dummy/config/boot.rb +6 -0
  99. data/spec/mongoid_dummy/config/environment.rb +5 -0
  100. data/spec/mongoid_dummy/config/environments/development.rb +31 -0
  101. data/spec/mongoid_dummy/config/environments/production.rb +64 -0
  102. data/spec/mongoid_dummy/config/environments/test.rb +35 -0
  103. data/spec/mongoid_dummy/config/initializers/backtrace_silencers.rb +7 -0
  104. data/spec/mongoid_dummy/config/initializers/generators.rb +2 -0
  105. data/spec/mongoid_dummy/config/initializers/include_acts_as_api.rb +3 -0
  106. data/spec/mongoid_dummy/config/initializers/inflections.rb +15 -0
  107. data/spec/mongoid_dummy/config/initializers/mime_types.rb +5 -0
  108. data/spec/mongoid_dummy/config/initializers/secret_token.rb +7 -0
  109. data/spec/mongoid_dummy/config/initializers/session_store.rb +8 -0
  110. data/spec/mongoid_dummy/config/initializers/wrap_parameters.rb +10 -0
  111. data/spec/mongoid_dummy/config/locales/en.yml +5 -0
  112. data/spec/mongoid_dummy/config/mongoid.yml +120 -0
  113. data/spec/mongoid_dummy/config/routes.rb +59 -0
  114. data/spec/mongoid_dummy/db/seeds.rb +7 -0
  115. data/spec/mongoid_dummy/doc/README_FOR_APP +2 -0
  116. data/spec/mongoid_dummy/lib/assets/.gitkeep +0 -0
  117. data/spec/mongoid_dummy/lib/tasks/.gitkeep +0 -0
  118. data/spec/mongoid_dummy/log/.gitkeep +0 -0
  119. data/spec/mongoid_dummy/public/404.html +26 -0
  120. data/spec/mongoid_dummy/public/422.html +26 -0
  121. data/spec/mongoid_dummy/public/500.html +25 -0
  122. data/spec/mongoid_dummy/public/favicon.ico +0 -0
  123. data/spec/mongoid_dummy/public/index.html +241 -0
  124. data/spec/mongoid_dummy/public/robots.txt +5 -0
  125. data/spec/mongoid_dummy/script/rails +6 -0
  126. data/spec/mongoid_dummy/vendor/assets/javascripts/.gitkeep +0 -0
  127. data/spec/mongoid_dummy/vendor/assets/stylesheets/.gitkeep +0 -0
  128. data/spec/mongoid_dummy/vendor/plugins/.gitkeep +0 -0
  129. data/spec/shared_engine/.gitignore +7 -0
  130. data/spec/shared_engine/Gemfile +14 -0
  131. data/spec/shared_engine/MIT-LICENSE +20 -0
  132. data/spec/shared_engine/README.rdoc +3 -0
  133. data/spec/shared_engine/Rakefile +29 -0
  134. data/spec/shared_engine/app/assets/images/shared_engine/.gitkeep +0 -0
  135. data/spec/shared_engine/app/assets/javascripts/shared_engine/application.js +15 -0
  136. data/spec/shared_engine/app/assets/stylesheets/shared_engine/application.css +13 -0
  137. data/spec/shared_engine/app/controllers/shared_engine/application_controller.rb +4 -0
  138. data/spec/shared_engine/app/controllers/shared_engine/plain_objects_controller.rb +14 -0
  139. data/spec/shared_engine/app/controllers/shared_engine/respond_with_users_controller.rb +64 -0
  140. data/spec/shared_engine/app/controllers/shared_engine/users_controller.rb +71 -0
  141. data/spec/shared_engine/app/helpers/shared_engine/application_helper.rb +4 -0
  142. data/spec/shared_engine/app/models/plain_object.rb +17 -0
  143. data/spec/shared_engine/app/models/user_template.rb +154 -0
  144. data/spec/shared_engine/app/views/layouts/shared_engine/application.html.erb +14 -0
  145. data/spec/shared_engine/config/routes.rb +28 -0
  146. data/spec/shared_engine/dummy/README.rdoc +261 -0
  147. data/spec/shared_engine/dummy/Rakefile +7 -0
  148. data/spec/shared_engine/dummy/app/assets/javascripts/application.js +15 -0
  149. data/spec/shared_engine/dummy/app/assets/stylesheets/application.css +13 -0
  150. data/spec/shared_engine/dummy/app/controllers/application_controller.rb +3 -0
  151. data/spec/shared_engine/dummy/app/helpers/application_helper.rb +2 -0
  152. data/spec/shared_engine/dummy/app/mailers/.gitkeep +0 -0
  153. data/spec/shared_engine/dummy/app/models/.gitkeep +0 -0
  154. data/spec/shared_engine/dummy/app/views/layouts/application.html.erb +14 -0
  155. data/spec/shared_engine/dummy/config.ru +4 -0
  156. data/spec/shared_engine/dummy/config/application.rb +62 -0
  157. data/spec/shared_engine/dummy/config/boot.rb +10 -0
  158. data/spec/shared_engine/dummy/config/database.yml +25 -0
  159. data/spec/shared_engine/dummy/config/environment.rb +5 -0
  160. data/spec/shared_engine/dummy/config/environments/development.rb +37 -0
  161. data/spec/shared_engine/dummy/config/environments/production.rb +67 -0
  162. data/spec/shared_engine/dummy/config/environments/test.rb +37 -0
  163. data/spec/shared_engine/dummy/config/initializers/backtrace_silencers.rb +7 -0
  164. data/spec/shared_engine/dummy/config/initializers/inflections.rb +15 -0
  165. data/spec/shared_engine/dummy/config/initializers/mime_types.rb +5 -0
  166. data/spec/shared_engine/dummy/config/initializers/secret_token.rb +7 -0
  167. data/spec/shared_engine/dummy/config/initializers/session_store.rb +8 -0
  168. data/spec/shared_engine/dummy/config/initializers/wrap_parameters.rb +14 -0
  169. data/spec/shared_engine/dummy/config/locales/en.yml +5 -0
  170. data/spec/shared_engine/dummy/config/routes.rb +4 -0
  171. data/spec/shared_engine/dummy/lib/assets/.gitkeep +0 -0
  172. data/spec/shared_engine/dummy/log/.gitkeep +0 -0
  173. data/spec/shared_engine/dummy/public/404.html +26 -0
  174. data/spec/shared_engine/dummy/public/422.html +26 -0
  175. data/spec/shared_engine/dummy/public/500.html +25 -0
  176. data/spec/shared_engine/dummy/public/favicon.ico +0 -0
  177. data/spec/shared_engine/dummy/script/rails +6 -0
  178. data/spec/shared_engine/lib/magic/rails/engine.rb +69 -0
  179. data/spec/shared_engine/lib/shared_engine.rb +4 -0
  180. data/spec/shared_engine/lib/shared_engine/engine.rb +5 -0
  181. data/spec/shared_engine/lib/shared_engine/version.rb +3 -0
  182. data/spec/shared_engine/lib/tasks/shared_engine_tasks.rake +4 -0
  183. data/spec/shared_engine/script/rails +8 -0
  184. data/spec/shared_engine/shared_engine.gemspec +22 -0
  185. data/spec/spec.opts +1 -0
  186. data/spec/spec_helper.rb +22 -0
  187. data/spec/support/api_test_helpers.rb +23 -0
  188. data/spec/support/controller_examples.rb +458 -0
  189. data/spec/support/it_supports.rb +3 -0
  190. data/spec/support/model_examples/associations.rb +272 -0
  191. data/spec/support/model_examples/callbacks.rb +38 -0
  192. data/spec/support/model_examples/closures.rb +49 -0
  193. data/spec/support/model_examples/conditional_if.rb +165 -0
  194. data/spec/support/model_examples/conditional_unless.rb +165 -0
  195. data/spec/support/model_examples/enabled.rb +10 -0
  196. data/spec/support/model_examples/extending.rb +112 -0
  197. data/spec/support/model_examples/methods.rb +23 -0
  198. data/spec/support/model_examples/options.rb +53 -0
  199. data/spec/support/model_examples/renaming.rb +50 -0
  200. data/spec/support/model_examples/simple.rb +23 -0
  201. data/spec/support/model_examples/sub_nodes.rb +105 -0
  202. data/spec/support/model_examples/undefined.rb +7 -0
  203. data/spec/support/model_examples/untouched.rb +13 -0
  204. data/spec/support/routing.rb +4 -0
  205. data/spec/support/simple_fixtures.rb +59 -0
  206. metadata +499 -0
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>acts_as_api</title>
6
+ <meta content="A Ruby/Rails gem to easily generate web api reponses!" name="description" />
7
+ <meta content="Christian Bäuerlein" name="author" />
8
+ <meta content="en" name="language" />
9
+ <link rel="stylesheet" href="./docco.css">
10
+ <link href="http://fonts.googleapis.com/css?family=Copse:regular" rel="stylesheet" type="text/css" >
11
+ <style>
12
+ h1, h2, h3, h4, h5 {
13
+ font-family: 'Copse', serif;
14
+ font-style: normal;
15
+ font-weight: 700;
16
+ text-shadow: none;
17
+ text-decoration: none;
18
+ text-transform: none;
19
+ letter-spacing: 0em;
20
+ word-spacing: 0em;
21
+ line-height: 1.2;
22
+ }
23
+ </style>
24
+ </head>
25
+ <body>
26
+ <div id='container'>
27
+ <div id="background"></div>
28
+ {{#sources?}}
29
+ <div id="jump_to">
30
+ Jump To &hellip;
31
+ <div id="jump_wrapper">
32
+ <div id="jump_page">
33
+ {{#sources}}
34
+ <a class="source" href="{{ url }}">{{ basename }}</a>
35
+ {{/sources}}
36
+ </div>
37
+ </div>
38
+ </div>
39
+ {{/sources?}}
40
+ <table cellspacing=0 cellpadding=0>
41
+ <thead>
42
+ <tr>
43
+ <th class=docs>
44
+ <h1>acts_as_api</h1>
45
+ <p>Makes creating XML/JSON responses in Rails 3 easy and fun.</p>
46
+ </th>
47
+ <th class=code></th>
48
+ </tr>
49
+ </thead>
50
+ <tbody>
51
+ {{#sections}}
52
+ <tr id='section-{{ section_id }}'>
53
+ <td class=docs>
54
+ <div class="pilwrap">
55
+ <a class="pilcrow" href="#section-{{ section_id }}">&#182;</a>
56
+ </div>
57
+ {{{ docs }}}
58
+ </td>
59
+ <td class=code>
60
+ <div class='highlight'><pre>{{{ code }}}</pre></div>
61
+ </td>
62
+ </tr>
63
+ {{/sections}}
64
+ </table>
65
+ </div>
66
+ <a href="https://github.com/fabrik42/acts_as_api"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://assets1.github.com/img/7afbc8b248c68eb468279e8c17986ad46549fb71?repo=&url=http%3A%2F%2Fs3.amazonaws.com%2Fgithub%2Fribbons%2Fforkme_right_darkblue_121621.png&path=" alt="Fork me on GitHub"></a>
67
+ </body>
@@ -0,0 +1,46 @@
1
+ require 'active_model'
2
+ require 'active_support/core_ext/class'
3
+
4
+ $:.unshift(File.dirname(__FILE__)) unless
5
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
+
7
+ require "acts_as_api/array"
8
+ require "acts_as_api/rails_renderer"
9
+ require "acts_as_api/exceptions"
10
+
11
+ # acts_as_api is a gem that aims to make the construction of JSON and XML
12
+ # responses in rails 3 easy and fun.
13
+ #
14
+ # Therefore it attaches a couple of helper methods to active record and
15
+ # the action controller base classes.
16
+ #
17
+ # acts_as_api uses the default serializers of your rails app and doesn't
18
+ # force you into more dependencies.
19
+ module ActsAsApi
20
+ autoload :Config, "acts_as_api/config"
21
+ autoload :ApiTemplate, "acts_as_api/api_template"
22
+ autoload :Base, "acts_as_api/base"
23
+ autoload :Rendering, "acts_as_api/rendering"
24
+ autoload :Responder, "acts_as_api/responder"
25
+ autoload :Adapters, "acts_as_api/adapters"
26
+ end
27
+
28
+ # Attach ourselves to ActiveRecord
29
+ if defined?(ActiveRecord::Base)
30
+ ActiveRecord::Base.extend ActsAsApi::Base
31
+ end
32
+
33
+ # Attach ourselves to Mongoid
34
+ if defined?(Mongoid::Document)
35
+ Mongoid::Document.send :include, ActsAsApi::Adapters::Mongoid
36
+ end
37
+
38
+ if defined?(Sequel::Model)
39
+ Sequel::Model.extend ActsAsApi::Base
40
+ end
41
+
42
+ # Attach ourselves to the action controller of Rails
43
+ if defined?(ActionController::Base)
44
+ ActionController::Base.send :include, ActsAsApi::Rendering
45
+ ActsAsApi::RailsRenderer.setup
46
+ end
@@ -0,0 +1,5 @@
1
+ module ActsAsApi
2
+ module Adapters
3
+ autoload :Mongoid, "acts_as_api/adapters/mongoid"
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ module ActsAsApi
2
+ module Adapters
3
+ module Mongoid
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ extend ActsAsApi::Base
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,139 @@
1
+ module ActsAsApi
2
+ # Represents an api template for a model.
3
+ # This class should not be initiated by yourself, api templates
4
+ # are created by defining them in the model by calling: +api_accessible+.
5
+ #
6
+ # The api template is configured in the block passed to +api_accessible+.
7
+ #
8
+ # Please note that +ApiTemplate+ inherits from +Hash+ so you can use all
9
+ # kind of +Hash+ and +Enumerable+ methods to manipulate the template.
10
+ class ApiTemplate < Hash
11
+
12
+ # The name of the api template as a Symbol.
13
+ attr_accessor :api_template
14
+
15
+ attr_reader :options
16
+
17
+ def initialize(api_template)
18
+ self.api_template = api_template
19
+ @options ||= {}
20
+ end
21
+
22
+ def merge!(other_hash, &block)
23
+ super
24
+ self.options.merge!(other_hash.options) if other_hash.respond_to?(:options)
25
+ end
26
+
27
+ # Adds a field to the api template
28
+ #
29
+ # The value passed can be one of the following:
30
+ # * Symbol - the method with the same name will be called on the model when rendering.
31
+ # * String - must be in the form "method1.method2.method3", will call this method chain.
32
+ # * Hash - will be added as a sub hash and all its items will be resolved the way described above.
33
+ #
34
+ # Possible options to pass:
35
+ # * :template - Determine the template that should be used to render the item if it is
36
+ # +api_accessible+ itself.
37
+ def add(val, options = {})
38
+ item_key = (options[:as] || val).to_sym
39
+
40
+ self[item_key] = val
41
+
42
+ @options[item_key] = options
43
+ end
44
+
45
+ # Removes a field from the template
46
+ def remove(field)
47
+ self.delete(field)
48
+ end
49
+
50
+ # Returns the options of a field in the api template
51
+ def options_for(field)
52
+ @options[field]
53
+ end
54
+
55
+ # Returns the passed option of a field in the api template
56
+ def option_for(field, option)
57
+ @options[field][option] if @options[field]
58
+ end
59
+
60
+ # If a special template name for the passed item is specified
61
+ # it will be returned, if not the original api template.
62
+ def api_template_for(fieldset, field)
63
+ fieldset.option_for(field, :template) || api_template
64
+ end
65
+
66
+ # Decides if the passed item should be added to
67
+ # the response based on the conditional options passed.
68
+ def allowed_to_render?(fieldset, field, model, options)
69
+ return true unless fieldset.is_a? ActsAsApi::ApiTemplate
70
+
71
+ fieldset_options = fieldset.options_for(field)
72
+
73
+ if fieldset_options[:unless]
74
+ !(condition_fulfilled?(model, fieldset_options[:unless], options))
75
+ elsif fieldset_options[:if]
76
+ condition_fulfilled?(model, fieldset_options[:if], options)
77
+ else
78
+ true
79
+ end
80
+ end
81
+
82
+ # Checks if a condition is fulfilled
83
+ # (result is not nil or false)
84
+ def condition_fulfilled?(model, condition, options)
85
+ case condition
86
+ when Symbol
87
+ result = model.send(condition)
88
+ when Proc
89
+ result = call_proc(condition, model, options)
90
+ end
91
+ !!result
92
+ end
93
+
94
+ # Generates a hash that represents the api response based on this
95
+ # template for the passed model instance.
96
+ def to_response_hash(model, fieldset = self, options = {})
97
+ api_output = {}
98
+
99
+ fieldset.each do |field, value|
100
+ next unless allowed_to_render?(fieldset, field, model, options)
101
+
102
+ out = process_value(model, value, options)
103
+
104
+ if out.respond_to?(:as_api_response)
105
+ sub_template = api_template_for(fieldset, field)
106
+ out = out.as_api_response(sub_template, options)
107
+ end
108
+
109
+ api_output[field] = out
110
+ end
111
+
112
+ api_output
113
+ end
114
+
115
+ private
116
+
117
+ def process_value(model, value, options)
118
+ case value
119
+ when Symbol
120
+ model.send(value)
121
+ when Proc
122
+ call_proc(value,model,options)
123
+ when String
124
+ value.split('.').inject(model) { |result, method| result.send(method) }
125
+ when Hash
126
+ to_response_hash(model, value)
127
+ end
128
+ end
129
+
130
+ def call_proc(the_proc,model,options)
131
+ if the_proc.arity == 2
132
+ the_proc.call(model, options)
133
+ else
134
+ the_proc.call(model)
135
+ end
136
+ end
137
+
138
+ end
139
+ end
@@ -0,0 +1,21 @@
1
+ # The standard ruby Array class is extended by one instance method.
2
+ class Array
3
+
4
+ # Neccessary to render an Array of models, e.g. the result of a search.
5
+ #
6
+ # The Array checks all its items if they respond to the +as_api_response+ method.
7
+ # If they do, the result of this method will be collected.
8
+ # If they don't, the item itself will be collected.
9
+ def as_api_response(api_template, options = {})
10
+
11
+ collect do |item|
12
+ if item.respond_to?(:as_api_response)
13
+ item.as_api_response(api_template,options)
14
+ else
15
+ item
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,88 @@
1
+ module ActsAsApi
2
+ # This module enriches the ActiveRecord::Base module of Rails.
3
+ module Base
4
+ # Indicates if the current model acts as api.
5
+ # False by default.
6
+ def acts_as_api?
7
+ false
8
+ end
9
+
10
+ # When invoked, it enriches the current model with the
11
+ # class and instance methods to act as api.
12
+ def acts_as_api
13
+
14
+ class_eval do
15
+ include ActsAsApi::Base::InstanceMethods
16
+ extend ActsAsApi::Base::ClassMethods
17
+ end
18
+
19
+ if block_given?
20
+ yield ActsAsApi::Config
21
+ end
22
+
23
+ end
24
+
25
+ module ClassMethods
26
+
27
+ def acts_as_api?#:nodoc:
28
+ self.included_modules.include?(InstanceMethods)
29
+ end
30
+
31
+ # Determines the attributes, methods of the model that are accessible in the api response.
32
+ # *Note*: There is only whitelisting for api accessible attributes.
33
+ # So once the model acts as api, you have to determine all attributes here that should
34
+ # be contained in the api responses.
35
+ def api_accessible(api_template, options = {}, &block)
36
+
37
+ attributes = api_accessible_attributes(api_template).try(:dup) || ApiTemplate.new(api_template)
38
+
39
+ attributes.merge!(api_accessible_attributes(options[:extend])) if options[:extend]
40
+
41
+ if block_given?
42
+ yield attributes
43
+ end
44
+
45
+ class_attribute "api_accessible_#{api_template}".to_sym
46
+ send "api_accessible_#{api_template}=", attributes
47
+ end
48
+
49
+ # Returns an array of all the attributes that have been made accessible to the api response.
50
+ def api_accessible_attributes(api_template)
51
+ begin send "api_accessible_#{api_template}".to_sym rescue nil end
52
+ end
53
+ end
54
+
55
+ module InstanceMethods
56
+
57
+ # Creates the api response of the model and returns it as a Hash.
58
+ # Will raise an exception if the passed api template is not defined for the model
59
+ def as_api_response(api_template, options = {})
60
+ api_attributes = self.class.api_accessible_attributes(api_template)
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
+
63
+ before_api_response(api_template)
64
+ response_hash = around_api_response(api_template) do
65
+ api_attributes.to_response_hash(self, api_attributes, options)
66
+ end
67
+ after_api_response(api_template)
68
+
69
+ response_hash
70
+ end
71
+
72
+ protected
73
+
74
+ def before_api_response(api_remplate)
75
+ end
76
+
77
+ def after_api_response(api_remplate)
78
+ end
79
+
80
+ def around_api_response(api_remplate)
81
+ yield
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,58 @@
1
+ module ActsAsApi
2
+
3
+ module Config
4
+
5
+ class << self
6
+
7
+ attr_writer :accepted_api_formats, :dasherize_for, :include_root_in_json_collections, :add_root_node_for, :default_root, :allow_jsonp_callback, :add_http_status_to_jsonp_response
8
+
9
+ # The accepted response formats
10
+ # Default is <tt>[:xml, :json]</tt>
11
+ def accepted_api_formats
12
+ @accepted_api_formats || [:xml, :json]
13
+ end
14
+
15
+ # Holds formats that should be dasherized
16
+ # Default is <tt>[:xml]</tt>
17
+ def dasherize_for
18
+ @dasherize_for || [:xml]
19
+ end
20
+
21
+ # If true, the root node in json collections will be added
22
+ # so the response will look like the default Rails 3 json
23
+ # response
24
+ def include_root_in_json_collections
25
+ @include_root_in_json_collections || false
26
+ end
27
+
28
+ # Holds references to formats that need
29
+ # to get added an additional root node
30
+ # with the name of the model.
31
+ def add_root_node_for
32
+ @add_root_node_for || [:json]
33
+ end
34
+
35
+ # The default name of a root node of a response
36
+ # if no root paramter is passed in render_for_api
37
+ # and the gem is not able to determine a root name
38
+ # automatically
39
+ def default_root
40
+ @default_root || :record
41
+ end
42
+
43
+ # If true a json response will be automatically wrapped into
44
+ # a JavaScript function call in case a :callback param is passed.
45
+ def allow_jsonp_callback
46
+ @allow_jsonp_callback || false
47
+ end
48
+
49
+ # If true the jsonp function call will get the http status passed
50
+ # as a second parameter
51
+ def add_http_status_to_jsonp_response
52
+ @add_http_status_to_jsonp_response.nil? ? true : @add_http_status_to_jsonp_response
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,4 @@
1
+ module ActsAsApi
2
+ class ActsAsApiError < RuntimeError; end
3
+ class TemplateNotFoundError < ActsAsApiError; end
4
+ end