restapi 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/Gemfile +2 -1
  2. data/Gemfile.lock +83 -64
  3. data/README.rdoc +375 -2
  4. data/app/controllers/restapi/restapis_controller.rb +21 -3
  5. data/app/helpers/restapi/restapis_helper.rb +31 -0
  6. data/app/public/restapi/javascripts/bundled/prettify.js +28 -0
  7. data/app/public/restapi/javascripts/restapi.js +4 -13
  8. data/app/public/restapi/stylesheets/bundled/prettify.css +30 -0
  9. data/app/views/layouts/restapi/restapi.html.erb +36 -0
  10. data/app/views/restapi/restapis/index.html.erb +35 -33
  11. data/app/views/restapi/restapis/method.html.erb +59 -0
  12. data/app/views/restapi/restapis/resource.html.erb +71 -0
  13. data/app/views/restapi/restapis/static.html.erb +103 -0
  14. data/lib/restapi.rb +0 -10
  15. data/lib/restapi/application.rb +25 -10
  16. data/lib/restapi/dsl_definition.rb +38 -32
  17. data/lib/restapi/markup.rb +12 -12
  18. data/lib/restapi/method_description.rb +10 -8
  19. data/lib/restapi/param_description.rb +23 -10
  20. data/lib/restapi/resource_description.rb +1 -1
  21. data/lib/restapi/restapi_module.rb +15 -0
  22. data/lib/restapi/validator.rb +37 -14
  23. data/lib/restapi/version.rb +1 -1
  24. data/lib/tasks/restapi.rake +157 -0
  25. data/restapi.gemspec +1 -1
  26. data/spec/controllers/restapis_controller_spec.rb +84 -0
  27. data/spec/controllers/users_controller_spec.rb +273 -221
  28. data/spec/dummy/app/controllers/twitter_example_controller.rb +209 -208
  29. data/spec/dummy/app/controllers/users_controller.rb +23 -33
  30. data/spec/dummy/config/initializers/restapi.rb +45 -23
  31. data/spec/dummy/config/routes.rb +12 -7
  32. metadata +26 -15
  33. data/app/public/restapi/javascripts/bundled/backbone.js +0 -1431
  34. data/app/public/restapi/javascripts/bundled/json2.js +0 -487
  35. data/app/public/restapi/javascripts/bundled/underscore.js +0 -999
  36. data/app/public/restapi/javascripts/jst.js +0 -127
  37. data/app/public/restapi/javascripts/routers/documentation_router.js +0 -52
  38. data/app/public/restapi/stylesheets/bundled/bootstrap-responsive.css +0 -686
  39. data/app/public/restapi/stylesheets/bundled/bootstrap.css +0 -3990
  40. data/spec/dummy/app/controllers/dogs_controller.rb +0 -20
  41. data/spec/dummy/app/helpers/application_helper.rb +0 -2
@@ -3,12 +3,11 @@ class TwitterExampleController < ApplicationController
3
3
  resource_description do
4
4
  name 'Users'
5
5
  short_description 'Users are at the center of everything Twitter: they follow, they favorite, and tweet & retweet.'
6
- path '/users/'
6
+ path '/twitter_example/'
7
+ description "Long description of this resource."
7
8
  end
8
9
 
9
- api :desc => 'Return up to 100 users worth of extended information, specified by either ID, screen name, or combination of the two.',
10
- :path => '/users/lookup',
11
- :method => 'GET'
10
+ api :GET, '/twitter_example/lookup', 'Return up to 100 users worth of extended information, specified by either ID, screen name, or combination of the two.'
12
11
  param :screen_name, String, :desc => 'A comma separated list of screen names, up to 100 are allowed in a single request. You are strongly encouraged to use a POST for larger (up to 100 screen names) requests.'
13
12
  param :user_id, Integer, :desc => 'A comma separated list of user IDs, up to 100 are allowed in a single request. You are strongly encouraged to use a POST for larger requests.'
14
13
  param :include_entities, String, :desc => 'When set to either <code>true</code>, <code>t</code> or <code>1</code>, each tweet will include a node called "entities,". This node offers a variety of metadata about the tweet in a discreet structure, including: user_mentions, urls, and hashtags. While entities are opt-in on timelines at present, they will be made a default component of output in the future. See Tweet Entities for more detail on entities.'
@@ -30,9 +29,7 @@ class TwitterExampleController < ApplicationController
30
29
  render :text => "lookup"
31
30
  end
32
31
 
33
- api :desc => 'Access the profile image in various sizes for the user with the indicated screen_name.',
34
- :path => '/users/profile_image/:screen_name',
35
- :method => 'GET'
32
+ api :GET, '/twitter_example/profile_image/:screen_name', 'Access the profile image in various sizes for the user with the indicated screen_name.'
36
33
  param :screen_name, String, :required => true, :desc => 'The screen name of the user for whom to return results for. Helpful for disambiguating when a valid screen name is also a user ID.'
37
34
  param :size, ['bigger','normal','mini','original'], :desc => <<-EOS
38
35
  Specifies the size of image to fetch. Not specifying a size will give the default, normal size of 48px by 48px. Valid options include:
@@ -50,11 +47,10 @@ class TwitterExampleController < ApplicationController
50
47
  This method should only be used by application developers to lookup or check the profile image URL for a user. This method must not be used as the image source URL presented to users of your application.
51
48
  EOS
52
49
  def profile_image
53
- render :text => "profile_image"
50
+ render :text => "profile_image of '#{params[:screen_name]}'"
54
51
  end
55
52
 
56
- api :path => '/users/search', :method => 'GET',
57
- :desc => 'Runs a search for users similar to Find People button on Twitter.com.'
53
+ api :GET, '/twitter_example/search', 'Runs a search for users similar to Find People button on Twitter.com.'
58
54
  param :q, String, :desc => 'The search query to run against people search.', :required => true
59
55
  param :page, Integer, :desc => 'Specifies the page of results to retrieve.'
60
56
  param :per_page, Integer, :desc => 'The number of people to retrieve. Maxiumum of 20 allowed per page.'
@@ -66,93 +62,95 @@ class TwitterExampleController < ApplicationController
66
62
 
67
63
  === Extended description
68
64
  This method has a feature-specific rate limit of 60 calls per hour that is applied in conjunction with the main REST API rate limit. Calls to this method will count against the feature-specific rate limit and the main REST API rate limit. If either limit is exhausted, the request will fail. You can monitor the status of the feature-specific rate limit by inspecting the HTTP response headers <tt>X-FeatureRateLimit-Limit</tt>, <tt>X-FeatureRateLimit-Remaining</tt>, and <tt>X-FeatureRateLimit-Reset</tt>. These headers correspond to the <tt>X-RateLimit</tt> headers provided by the main REST API limit.
69
- [
70
- {
71
- "name": "Twitter API",
72
- "profile_sidebar_border_color": "87bc44",
73
- "profile_background_tile": false,
74
- "profile_sidebar_fill_color": "e0ff92",
75
- "location": "San Francisco, CA",
76
- "profile_image_url": "http://a3.twimg.com/profile_images/689684365/api_normal.png",
77
- "created_at": "Wed May 23 06:01:13 +0000 2007",
78
- "profile_link_color": "0000ff",
79
- "favourites_count": 2,
80
- "url": "http://apiwiki.twitter.com",
81
- "contributors_enabled": true,
82
- "utc_offset": -28800,
83
- "id": 6253282,
84
- "profile_use_background_image": true,
85
- "profile_text_color": "000000",
86
- "protected": false,
87
- "followers_count": 160753,
88
- "lang": "en",
89
- "verified": true,
90
- "profile_background_color": "c1dfee",
91
- "geo_enabled": true,
92
- "notifications": null,
93
- "description": "The Real Twitter API. I tweet about API changes, service issues and happily answer questions about Twitter and our API. Don't get an answer? It's on my website.",
94
- "time_zone": "Pacific Time (US & Canada)",
95
- "friends_count": 19,
96
- "statuses_count": 1858,
97
- "profile_background_image_url": "http://a3.twimg.com/profile_background_images/59931895/twitterapi-background-new.png",
98
- "status": {
99
- "coordinates": null,
100
- "favorited": false,
101
- "created_at": "Tue Jun 22 16:53:28 +0000 2010",
102
- "truncated": false,
103
- "text": "@Demonicpagan possible some part of your signature generation is incorrect & fails for real reasons.. follow up on the list if you suspect",
104
- "contributors": null,
105
- "id": 16783999399,
106
- "geo": null,
107
- "in_reply_to_user_id": 6339722,
108
- "place": null,
109
- "source": "<a href="http://www.tweetdeck.com" rel="nofollow">TweetDeck</a>",
110
- "in_reply_to_screen_name": "Demonicpagan",
111
- "in_reply_to_status_id": 16781827477
112
- },
113
- "screen_name": "twitterapi",
114
- "following": null
115
- },
116
- ...
117
- {
118
- "name": "twitterAPI",
119
- "profile_sidebar_border_color": "87bc44",
120
- "profile_background_tile": false,
121
- "profile_sidebar_fill_color": "e0ff92",
122
- "location": null,
123
- "profile_image_url": "http://s.twimg.com/a/1277162817/images/default_profile_6_normal.png",
124
- "created_at": "Fri Jun 04 12:07:25 +0000 2010",
125
- "profile_link_color": "0000ff",
126
- "favourites_count": 0,
127
- "url": null,
128
- "contributors_enabled": false,
129
- "utc_offset": null,
130
- "id": 151851125,
131
- "profile_use_background_image": true,
132
- "profile_text_color": "000000",
133
- "protected": false,
134
- "followers_count": 0,
135
- "lang": "ja",
136
- "verified": false,
137
- "profile_background_color": "9ae4e8",
138
- "geo_enabled": false,
139
- "notifications": false,
140
- "description": null,
141
- "time_zone": null,
142
- "friends_count": 0,
143
- "statuses_count": 0,
144
- "profile_background_image_url": "http://s.twimg.com/a/1277162817/images/themes/theme1/bg.png",
145
- "screen_name": "popoAPI",
146
- "following": false
147
- }
148
- ]
149
65
  EOS
66
+
67
+ example <<-EDOC
68
+ [
69
+ {
70
+ "name": "Twitter API",
71
+ "profile_sidebar_border_color": "87bc44",
72
+ "profile_background_tile": false,
73
+ "profile_sidebar_fill_color": "e0ff92",
74
+ "location": "San Francisco, CA",
75
+ "profile_image_url": "http://a3.twimg.com/profile_images/689684365/api_normal.png",
76
+ "created_at": "Wed May 23 06:01:13 +0000 2007",
77
+ "profile_link_color": "0000ff",
78
+ "favourites_count": 2,
79
+ "url": "http://apiwiki.twitter.com",
80
+ "contributors_enabled": true,
81
+ "utc_offset": -28800,
82
+ "id": 6253282,
83
+ "profile_use_background_image": true,
84
+ "profile_text_color": "000000",
85
+ "protected": false,
86
+ "followers_count": 160753,
87
+ "lang": "en",
88
+ "verified": true,
89
+ "profile_background_color": "c1dfee",
90
+ "geo_enabled": true,
91
+ "notifications": null,
92
+ "description": "The Real Twitter API. I tweet about API changes, service issues and happily answer questions about Twitter and our API. Don't get an answer? It's on my website.",
93
+ "time_zone": "Pacific Time (US & Canada)",
94
+ "friends_count": 19,
95
+ "statuses_count": 1858,
96
+ "profile_background_image_url": "http://a3.twimg.com/profile_background_images/59931895/twitterapi-background-new.png",
97
+ "status": {
98
+ "coordinates": null,
99
+ "favorited": false,
100
+ "created_at": "Tue Jun 22 16:53:28 +0000 2010",
101
+ "truncated": false,
102
+ "text": "@Demonicpagan possible some part of your signature generation is incorrect & fails for real reasons.. follow up on the list if you suspect",
103
+ "contributors": null,
104
+ "id": 16783999399,
105
+ "geo": null,
106
+ "in_reply_to_user_id": 6339722,
107
+ "place": null,
108
+ "source": "<a href="http://www.tweetdeck.com" rel="nofollow">TweetDeck</a>",
109
+ "in_reply_to_screen_name": "Demonicpagan",
110
+ "in_reply_to_status_id": 16781827477
111
+ },
112
+ "screen_name": "twitterapi",
113
+ "following": null
114
+ },
115
+ ...
116
+ {
117
+ "name": "twitterAPI",
118
+ "profile_sidebar_border_color": "87bc44",
119
+ "profile_background_tile": false,
120
+ "profile_sidebar_fill_color": "e0ff92",
121
+ "location": null,
122
+ "profile_image_url": "http://s.twimg.com/a/1277162817/images/default_profile_6_normal.png",
123
+ "created_at": "Fri Jun 04 12:07:25 +0000 2010",
124
+ "profile_link_color": "0000ff",
125
+ "favourites_count": 0,
126
+ "url": null,
127
+ "contributors_enabled": false,
128
+ "utc_offset": null,
129
+ "id": 151851125,
130
+ "profile_use_background_image": true,
131
+ "profile_text_color": "000000",
132
+ "protected": false,
133
+ "followers_count": 0,
134
+ "lang": "ja",
135
+ "verified": false,
136
+ "profile_background_color": "9ae4e8",
137
+ "geo_enabled": false,
138
+ "notifications": false,
139
+ "description": null,
140
+ "time_zone": null,
141
+ "friends_count": 0,
142
+ "statuses_count": 0,
143
+ "profile_background_image_url": "http://s.twimg.com/a/1277162817/images/themes/theme1/bg.png",
144
+ "screen_name": "popoAPI",
145
+ "following": false
146
+ }
147
+ ]
148
+ EDOC
150
149
  def search
151
150
  render :text => 'search'
152
151
  end
153
152
 
154
- api :path => '/users/show', :method => 'GET',
155
- :desc => 'Returns extended information of a given user, specified by ID or screen name as per the required id parameter.'
153
+ api :GET, '/twitter_example/show', 'Returns extended information of a given user, specified by ID or screen name as per the required id parameter.'
156
154
  param :user_id, Integer, :required => true, :desc => <<-EOS
157
155
  The ID of the user for whom to return results for. Either an id or screen_name is required for this method.
158
156
  _Note_: Specifies the ID of the user to befriend. Helpful for disambiguating when a valid user ID is also a valid screen name.
@@ -163,137 +161,140 @@ class TwitterExampleController < ApplicationController
163
161
 
164
162
  You must be following a protected user to be able to see their most recent status update. If you don't follow a protected user, or request this method without autenticating, the users status will be removed.
165
163
 
166
- The URL pattern <tt>/version/users/show/:screen_name_or_user_id.format</tt> is still accepted but not recommended. As a sequence of numbers is a valid screen name we recommend using the +screen_name+ or +user_id+ parameter instead.
164
+ The URL pattern <tt>/version/twitter_example/show/:screen_name_or_user_id.format</tt> is still accepted but not recommended. As a sequence of numbers is a valid screen name we recommend using the +screen_name+ or +user_id+ parameter instead.
167
165
  EDOC
168
166
  def show
169
167
  render :text => 'show'
170
168
  end
171
169
 
172
- api :path => '/users/contributors', :method => 'GET',
173
- :description => 'Returns an array of users who can contribute to the specified account.'
170
+ api :GET, '/twitter_example/contributors', 'Returns an array of users who can contribute to the specified account.'
174
171
  param :user_id, Integer, :desc => 'The ID of the user for whom to return results for. Helpful for disambiguating when a valid user ID is also a valid screen name.'
175
172
  param :screen_name, String, :desc => 'The screen name of the user for whom to return results for. Helpful for disambiguating when a valid screen name is also a user ID.'
176
173
  param :include_entities, String
177
174
  param :skip_status, ['t','true','1'],
178
175
  :description => 'When set to either true, t or 1 statuses will not be included in the returned user objects.'
179
-
180
- description <<-EDOC
181
- === Example request
182
- GET https://api.twitter.com/1/users/contributors.json?screen_name=twitterapi&include_entities=true&skip_status=true
183
- [
184
- {
185
- "profile_sidebar_border_color": "C0DEED",
186
- "profile_background_tile": false,
187
- "name": "Matt Harris",
188
- "profile_sidebar_fill_color": "DDEEF6",
189
- "expanded_url": "http://themattharris.com",
190
- "created_at": "Sat Feb 17 20:49:54 +0000 2007",
191
- "location": "SFO/LHR/YVR/JAX/IAD/AUS",
192
- "profile_image_url": "http://a1.twimg.com/profile_images/554181350/matt_normal.jpg",
193
- "follow_request_sent": false,
194
- "is_translator": false,
195
- "profile_link_color": "0084B4",
196
- "id_str": "777925",
197
- "entities": {
198
- "urls": [
199
176
 
200
- ],
201
- "hashtags": [
177
+ description "Look at examples."
178
+
179
+ example <<-EDOC
180
+ GET https://api.twitter.com/1/twitter_example/contributors.json?screen_name=twitterapi&include_entities=true&skip_status=true
181
+ [
182
+ {
183
+ "profile_sidebar_border_color": "C0DEED",
184
+ "profile_background_tile": false,
185
+ "name": "Matt Harris",
186
+ "profile_sidebar_fill_color": "DDEEF6",
187
+ "expanded_url": "http://themattharris.com",
188
+ "created_at": "Sat Feb 17 20:49:54 +0000 2007",
189
+ "location": "SFO/LHR/YVR/JAX/IAD/AUS",
190
+ "profile_image_url": "http://a1.twimg.com/profile_images/554181350/matt_normal.jpg",
191
+ "follow_request_sent": false,
192
+ "is_translator": false,
193
+ "profile_link_color": "0084B4",
194
+ "id_str": "777925",
195
+ "entities": {
196
+ "urls": [
197
+
198
+ ],
199
+ "hashtags": [
202
200
 
203
- ],
204
- "user_mentions": [
205
- {
206
- "name": "Cindy Li",
207
- "id_str": "29733",
208
- "id": 29733,
209
- "indices": [
210
- 45,
211
- 53
212
- ],
213
- "screen_name": "cindyli"
214
- }
215
- ]
216
- },
217
- "default_profile": true,
218
- "url": "http://t.co/292MnqA",
219
- "contributors_enabled": false,
220
- "favourites_count": 120,
221
- "id": 777925,
222
- "utc_offset": -28800,
223
- "listed_count": 271,
224
- "profile_use_background_image": true,
225
- "followers_count": 6242,
226
- "lang": "en",
227
- "protected": false,
228
- "profile_text_color": "333333",
229
- "profile_background_color": "C0DEED",
230
- "time_zone": "Pacific Time (US & Canada)",
231
- "geo_enabled": true,
232
- "description": "Developer Advocate at Twitter and married to @cindyli. NASA enthusiast, British expat and all around geek living in San Francisco.",
233
- "notifications": false,
234
- "verified": false,
235
- "profile_background_image_url": "http://a0.twimg.com/images/themes/theme1/bg.png",
236
- "statuses_count": 3835,
237
- "display_url": "themattharris.com",
238
- "friends_count": 360,
239
- "default_profile_image": false,
240
- "following": false,
241
- "show_all_inline_media": false,
242
- "screen_name": "themattharris"
201
+ ],
202
+ "user_mentions": [
203
+ {
204
+ "name": "Cindy Li",
205
+ "id_str": "29733",
206
+ "id": 29733,
207
+ "indices": [
208
+ 45,
209
+ 53
210
+ ],
211
+ "screen_name": "cindyli"
212
+ }
213
+ ]
243
214
  },
244
- ...
245
- {
246
- "profile_sidebar_border_color": "547980",
247
- "profile_background_tile": true,
248
- "name": "Ryan Sarver",
249
- "profile_sidebar_fill_color": "F8FCF2",
250
- "expanded_url": "http://sarver.org",
251
- "created_at": "Mon Feb 26 18:05:55 +0000 2007",
252
- "location": "San Francisco, CA",
253
- "profile_image_url": "http://a2.twimg.com/profile_images/644997837/ryan_sarver_twitter_big_normal.jpg",
254
- "follow_request_sent": false,
255
- "is_translator": false,
256
- "profile_link_color": "547980",
257
- "id_str": "795649",
258
- "entities": {
259
- "urls": [
215
+ "default_profile": true,
216
+ "url": "http://t.co/292MnqA",
217
+ "contributors_enabled": false,
218
+ "favourites_count": 120,
219
+ "id": 777925,
220
+ "utc_offset": -28800,
221
+ "listed_count": 271,
222
+ "profile_use_background_image": true,
223
+ "followers_count": 6242,
224
+ "lang": "en",
225
+ "protected": false,
226
+ "profile_text_color": "333333",
227
+ "profile_background_color": "C0DEED",
228
+ "time_zone": "Pacific Time (US & Canada)",
229
+ "geo_enabled": true,
230
+ "description": "Developer Advocate at Twitter and married to @cindyli. NASA enthusiast, British expat and all around geek living in San Francisco.",
231
+ "notifications": false,
232
+ "verified": false,
233
+ "profile_background_image_url": "http://a0.twimg.com/images/themes/theme1/bg.png",
234
+ "statuses_count": 3835,
235
+ "display_url": "themattharris.com",
236
+ "friends_count": 360,
237
+ "default_profile_image": false,
238
+ "following": false,
239
+ "show_all_inline_media": false,
240
+ "screen_name": "themattharris"
241
+ },
242
+ ...
243
+ ]
244
+ EDOC
245
+ example <<-EDOC
246
+ Another example...
247
+ {
248
+ "profile_sidebar_border_color": "547980",
249
+ "profile_background_tile": true,
250
+ "name": "Ryan Sarver",
251
+ "profile_sidebar_fill_color": "F8FCF2",
252
+ "expanded_url": "http://sarver.org",
253
+ "created_at": "Mon Feb 26 18:05:55 +0000 2007",
254
+ "location": "San Francisco, CA",
255
+ "profile_image_url": "http://a2.twimg.com/profile_images/644997837/ryan_sarver_twitter_big_normal.jpg",
256
+ "follow_request_sent": false,
257
+ "is_translator": false,
258
+ "profile_link_color": "547980",
259
+ "id_str": "795649",
260
+ "entities": {
261
+ "urls": [
260
262
 
261
- ],
262
- "hashtags": [
263
+ ],
264
+ "hashtags": [
263
265
 
264
- ],
265
- "user_mentions": [
266
+ ],
267
+ "user_mentions": [
266
268
 
267
- ]
268
- },
269
- "default_profile": false,
270
- "contributors_enabled": true,
271
- "url": "http://t.co/Lzsetyk",
272
- "favourites_count": 246,
273
- "id": 795649,
274
- "utc_offset": -28800,
275
- "profile_use_background_image": true,
276
- "listed_count": 1384,
277
- "followers_count": 280756,
278
- "lang": "en",
279
- "protected": false,
280
- "profile_text_color": "594F4F",
281
- "profile_background_color": "45ADA8",
282
- "time_zone": "Pacific Time (US & Canada)",
283
- "geo_enabled": true,
284
- "description": "platform/api at twitter",
285
- "notifications": false,
286
- "verified": false,
287
- "friends_count": 1022,
288
- "profile_background_image_url": "http://a0.twimg.com/profile_background_images/113854313/xa60e82408188860c483d73444d53e21.png",
289
- "display_url": "sarver.org",
290
- "default_profile_image": false,
291
- "statuses_count": 7031,
292
- "following": false,
293
- "show_all_inline_media": true,
294
- "screen_name": "rsarver"
295
- }
296
- ]
269
+ ]
270
+ },
271
+ "default_profile": false,
272
+ "contributors_enabled": true,
273
+ "url": "http://t.co/Lzsetyk",
274
+ "favourites_count": 246,
275
+ "id": 795649,
276
+ "utc_offset": -28800,
277
+ "profile_use_background_image": true,
278
+ "listed_count": 1384,
279
+ "followers_count": 280756,
280
+ "lang": "en",
281
+ "protected": false,
282
+ "profile_text_color": "594F4F",
283
+ "profile_background_color": "45ADA8",
284
+ "time_zone": "Pacific Time (US & Canada)",
285
+ "geo_enabled": true,
286
+ "description": "platform/api at twitter",
287
+ "notifications": false,
288
+ "verified": false,
289
+ "friends_count": 1022,
290
+ "profile_background_image_url": "http://a0.twimg.com/profile_background_images/113854313/xa60e82408188860c483d73444d53e21.png",
291
+ "display_url": "sarver.org",
292
+ "default_profile_image": false,
293
+ "statuses_count": 7031,
294
+ "following": false,
295
+ "show_all_inline_media": true,
296
+ "screen_name": "rsarver"
297
+ }
297
298
  EDOC
298
299
  def contributors
299
300
  render :text => 'contributors'
@@ -303,4 +304,4 @@ class TwitterExampleController < ApplicationController
303
304
  render :text => 'twitter example'
304
305
  end
305
306
 
306
- end
307
+ end