episodic-platform 0.9

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 (36) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +35 -0
  3. data/PostInstall.txt +7 -0
  4. data/README.rdoc +86 -0
  5. data/Rakefile +45 -0
  6. data/lib/episodic/platform.rb +82 -0
  7. data/lib/episodic/platform/analytics_methods.rb +190 -0
  8. data/lib/episodic/platform/base.rb +64 -0
  9. data/lib/episodic/platform/collection_response.rb +45 -0
  10. data/lib/episodic/platform/connection.rb +305 -0
  11. data/lib/episodic/platform/exceptions.rb +105 -0
  12. data/lib/episodic/platform/query_methods.rb +721 -0
  13. data/lib/episodic/platform/response.rb +94 -0
  14. data/lib/episodic/platform/write_methods.rb +446 -0
  15. data/script/console +10 -0
  16. data/script/destroy +14 -0
  17. data/script/generate +14 -0
  18. data/test/fixtures/1-0.mp4 +0 -0
  19. data/test/fixtures/create-episode-response-s3.xml +15 -0
  20. data/test/fixtures/create-episode-response.xml +3 -0
  21. data/test/fixtures/episodes-response.xml +408 -0
  22. data/test/fixtures/episodes-summary-report-response.xml +4 -0
  23. data/test/fixtures/invalid-param-response-multiple.xml +8 -0
  24. data/test/fixtures/invalid-param-response-single.xml +9 -0
  25. data/test/fixtures/playlists-response.xml +611 -0
  26. data/test/fixtures/shows-response.xml +26 -0
  27. data/test/test_analytics_requests.rb +42 -0
  28. data/test/test_analytics_responses.rb +14 -0
  29. data/test/test_connection.rb +31 -0
  30. data/test/test_error_responses.rb +29 -0
  31. data/test/test_helper.rb +8 -0
  32. data/test/test_query_requests.rb +62 -0
  33. data/test/test_query_responses.rb +165 -0
  34. data/test/test_write_requests.rb +56 -0
  35. data/test/test_write_responses.rb +24 -0
  36. metadata +135 -0
@@ -0,0 +1,721 @@
1
+ module Episodic #:nodoc:
2
+
3
+ module Platform
4
+
5
+ #
6
+ # Class for making requests against the Episodic Platform Query API.
7
+ #
8
+ class QueryMethods < Base
9
+
10
+ class << self
11
+
12
+ #
13
+ # Queries for episodes in your network. The options parameter allows you to limit
14
+ # your results. Acceptable options are:
15
+ # show_id - A single id or an Array of show ids. If this param is not provided then
16
+ # all shows in your network are queried.
17
+ # id - A single id or an Array of episode ids. If this param is not provided then
18
+ # all episodes in the your network or specified shows are queried.
19
+ # search_term - This string is used to perform a keywords search against the title,
20
+ # description, tags and custom fields of an episode. Tags should be separated by
21
+ # commas.
22
+ # search_type - The search_type parameter must be one of "tags", "name_description"
23
+ # or "all". The default is "all"
24
+ # tag_mode - The tag_mode parameter can be "any" for an OR combination of tags, or
25
+ # "all" for an AND combination. The default is "any". This parameter is ignored if
26
+ # the search_type is not "tags".
27
+ # status - The status parameter can be used to limit the list of episodes with a
28
+ # certain publishing status. The value must be a comma delimited list of one or more
29
+ # of "off_the_air", "publishing", "on_the_air", "waiting_to_air", "publish_failed"
30
+ # sort_by - The sort_by parameter is optional and specifies a field to sort the results
31
+ # by. The value must be one of "updated_at", "created_at", "air_date" or "name".
32
+ # The default is "created_at".
33
+ # sort_dir - The sort_dir parameter is optional and specifies the sort direction. The
34
+ # value must be one of "asc" or "desc". The default is "asc".
35
+ # include_views - A value that must be one of "true" or "false" to indicate if total
36
+ # views and complete views should be included in the response. The default is "false".
37
+ # NOTE: Setting this to "true" may result in slower response times.
38
+ # page - A value that must be an integer indicating the page number to return the results
39
+ # for. The default is 1.
40
+ # per_page - A value that must be an integer indicating the number of items per page. The
41
+ # default is 20. NOTE: The smaller this value is the better your response times will be.
42
+ # embed_width - An integer value in pixels that specifies the width of the player. The
43
+ # returned embed code width may be larger that this to account for player controls
44
+ # depending on the player you are using. If only the width is provided, the height is
45
+ # determined by maintaining the aspect ratio.
46
+ # embed_height - An integer value in pixels that specifies the height of the player. The
47
+ # embed code height may be larger that this to account for player controls depending on
48
+ # the player you are using. The default height is 360.
49
+ #
50
+ # ==== Parameters
51
+ #
52
+ # options<Hash>:: A hash of optional attributes.
53
+ #
54
+ # ==== Returns
55
+ #
56
+ # ::Episodic::Platform::EpisodesResponse:: The parsed response.
57
+ #
58
+ def episodes options = {}
59
+
60
+ # Clone the options into our params hash
61
+ params = options.clone
62
+
63
+ # Make the request
64
+ response = connection.do_get(construct_url("query", "episodes"), params)
65
+
66
+ # Convert to a hash
67
+ return parse_episodes_response(response)
68
+ end
69
+
70
+ #
71
+ # Third-party applications can register to be notified of changes to episodes and
72
+ # playlists in their network by providing an Modification URL in their network settings.
73
+ # When an episode/playlist is created, modified or deleted the Episodic System when
74
+ # make a POST request to specified URL with an XML representation of the modified object.
75
+ #
76
+ # This method allows the caller to query for all callbacks registered since a specified time.
77
+ # Although, failed callbacks are marked as failed and retried, this method allows the caller
78
+ # to see a history of callbacks to perhaps reprocess them if something went wrong with their
79
+ # initial processing.
80
+ #
81
+ # Acceptable filter options are:
82
+ # pending_only - Set this parameter to 'true' if only unprocessed callbacks should be
83
+ # returned. The default is 'false'.
84
+ # page - A value that must be an integer indicating the page number to return the results
85
+ # for. The default is 1.
86
+ # per_page - A value that must be an integer indicating the number of items per page. The
87
+ # default is 20. NOTE: The smaller this value is the better your response times will be.
88
+ #
89
+ # ==== Parameters
90
+ #
91
+ # since<Time>:: All callbacks registered since the provided date will be included in the
92
+ # response.
93
+ # options<Hash>:: A hash of optional attributes.
94
+ #
95
+ # ==== Returns
96
+ #
97
+ # String:: The XML response from the server.
98
+ #
99
+ def modification_callbacks since, options = {}
100
+
101
+ # Clone the options into our params hash
102
+ params = options.clone
103
+ params[:since] = since
104
+
105
+ # Make the request
106
+ response = connection.do_get(construct_url("query", "modification_callbacks"), params)
107
+
108
+ # Convert to a hash
109
+ return response.body
110
+ end
111
+
112
+ #
113
+ # Queries for playlists in your network. The options parameter allows you to limit
114
+ # your results. Acceptable options are:
115
+ # show_id - A single id or an Array of show ids. If this param is not provided then
116
+ # all shows in your network are queried.
117
+ # id - A single id or an Array of playlist ids. If this param is not provided then
118
+ # all playlists in the your network or specified shows are queried.
119
+ # search_term - This string is used to perform a keywords search against the title,
120
+ # description, and custom fields of a playlist.
121
+ # sort_by - The sort_by parameter is optional and specifies a field to sort the results
122
+ # by. The value must be one of "updated_at", "created_at", "name".
123
+ # The default is "created_at".
124
+ # sort_dir - The sort_dir parameter is optional and specifies the sort direction. The
125
+ # value must be one of "asc" or "desc". The default is "asc".
126
+ # page - A value that must be an integer indicating the page number to return the results
127
+ # for. The default is 1.
128
+ # per_page - A value that must be an integer indicating the number of items per page. The
129
+ # default is 20. NOTE: The smaller this value is the better your response times will be.
130
+ # embed_width - An integer value in pixels that specifies the width of the player. The
131
+ # returned embed code width may be larger that this to account for player controls
132
+ # depending on the player you are using. If only the width is provided, the height is
133
+ # determined by maintaining the aspect ratio.
134
+ # embed_height - An integer value in pixels that specifies the height of the player. The
135
+ # embed code height may be larger that this to account for player controls depending on
136
+ # the player you are using. The default height is 360.
137
+ #
138
+ # ==== Parameters
139
+ #
140
+ # options<Hash>:: A hash of optional attributes.
141
+ #
142
+ # ==== Returns
143
+ #
144
+ # ::Episodic::Platform::PlaylistsResponse:: The parsed response.
145
+ #
146
+ def playlists options = {}
147
+
148
+ # Clone the options into our params hash
149
+ params = options.clone
150
+
151
+ # Make the request
152
+ response = connection.do_get(construct_url("query", "playlists"), params)
153
+
154
+ # Convert to a hash
155
+ return parse_playlists_response(response)
156
+ end
157
+
158
+ #
159
+ # Queries for shows in your network. The options parameter allows you to limit
160
+ # your results. Acceptable options are:
161
+ # id - A single id or an Array of episode ids. If this param is not provided then
162
+ # all shows in the your network or specified shows are queried.
163
+ # sort_by - The sort_by parameter is optional and specifies a field to sort the results
164
+ # by. The value must be one of "updated_at", "created_at" or "name". The
165
+ # default is "created_at".
166
+ # sort_dir - The sort_dir parameter is optional and specifies the sort direction. The
167
+ # value must be one of "asc" or "desc". The default is "asc".
168
+ # page - A value that must be an integer indicating the page number to return the results
169
+ # for. The default is 1.
170
+ # per_page - A value that must be an integer indicating the number of items per page. The
171
+ # default is 20. NOTE: The smaller this value is the better your response times will be.
172
+ #
173
+ # ==== Parameters
174
+ #
175
+ # options<Hash>:: A hash of optional attributes.
176
+ #
177
+ # ==== Returns
178
+ #
179
+ # ::Episodic::Platform::ShowsResponse:: The parsed response.
180
+ #
181
+ def shows options = {}
182
+
183
+ # Clone the options into our params hash
184
+ params = options.clone
185
+
186
+ # Make the request
187
+ response = connection.do_get(construct_url("query", "shows"), params)
188
+
189
+ # Convert to a hash
190
+ return parse_shows_response(response)
191
+ end
192
+
193
+ protected
194
+
195
+ #
196
+ # Method factored out to make unit testing easier. This method simply creates the <tt>::Episodic::Platform::EpisodesResponse</tt>
197
+ # object.
198
+ #
199
+ # ==== Parameters
200
+ #
201
+ # response<Episodic::Platform::HTTPResponse>:: The response from an episodes request
202
+ #
203
+ # ==== Returns
204
+ #
205
+ # ::Episodic::Platform::EpisodesResponse:: The parsed response.
206
+ #
207
+ def parse_episodes_response response
208
+ return ::Episodic::Platform::EpisodesResponse.new(response, {"ForceArray" => ["episode", "thumbnail", "player", "download", "field", "playlist"]})
209
+ end
210
+
211
+ #
212
+ # Method factored out to make unit testing easier. This method simply creates the <tt>::Episodic::Platform::ShowsResponse</tt>
213
+ # object.
214
+ #
215
+ # ==== Parameters
216
+ #
217
+ # response<Episodic::Platform::HTTPResponse>:: The response from a shows request
218
+ #
219
+ # ==== Returns
220
+ #
221
+ # ::Episodic::Platform::EpisodesResponse:: The parsed response.
222
+ #
223
+ def parse_shows_response response
224
+ return ::Episodic::Platform::ShowsResponse.new(response, {"ForceArray" => ["show", "thumbnail", "player"]})
225
+ end
226
+
227
+ #
228
+ # Method factored out to make unit testing easier. This method simply creates the <tt>::Episodic::Platform::PlaylistsResponse</tt>
229
+ # object.
230
+ #
231
+ # ==== Parameters
232
+ #
233
+ # response<Episodic::Platform::HTTPResponse>:: The response from a playlists request
234
+ #
235
+ # ==== Returns
236
+ #
237
+ # ::Episodic::Platform::EpisodesResponse:: The parsed response.
238
+ #
239
+ def parse_playlists_response response
240
+ return ::Episodic::Platform::PlaylistsResponse.new(response, {"ForceArray" => ["playlist", "thumbnail", "player", "field", "episode"]})
241
+ end
242
+
243
+ end
244
+ end
245
+
246
+ #
247
+ # Extends <tt>Episodic::Platform::CollectionResponse</tt> to handle a collection of shows in the response.
248
+ #
249
+ class ShowsResponse < CollectionResponse
250
+
251
+ #
252
+ # Get the list of shows from the response.
253
+ #
254
+ # ==== Returns
255
+ #
256
+ # Array:: An array of <tt>Episodic::Platform::ShowItem</tt> objects.
257
+ #
258
+ def shows
259
+ @show_items ||= @parsed_body["show"].collect {|e| ShowItem.new(e)}
260
+ return @show_items
261
+ end
262
+
263
+ end
264
+
265
+ #
266
+ # Extends <tt>Episodic::Platform::CollectionResponse</tt> to handle a collection of episodes in the response.
267
+ #
268
+ class EpisodesResponse < CollectionResponse
269
+
270
+ #
271
+ # Get the list of episodes from the response.
272
+ #
273
+ # ==== Returns
274
+ #
275
+ # Array:: An array of <tt>Episodic::Platform::EpisodeItem</tt> objects.
276
+ #
277
+ def episodes
278
+ @episode_items ||= @parsed_body["episode"].collect {|e| EpisodeItem.new(e)}
279
+ return @episode_items
280
+ end
281
+
282
+ end
283
+
284
+ #
285
+ # Extends <tt>Episodic::Platform::CollectionResponse</tt> to handle a collection of playlists in the response.
286
+ #
287
+ class PlaylistsResponse < CollectionResponse
288
+
289
+ #
290
+ # Get the list of playlists from the response.
291
+ #
292
+ # ==== Returns
293
+ #
294
+ # Array:: An array of <tt>Episodic::Platform::EpisodeItem</tt> objects.
295
+ #
296
+ def playlists
297
+ @playlist_items ||= @parsed_body["playlist"].collect {|e| PlaylistItem.new(e)}
298
+ return @playlist_items
299
+ end
300
+
301
+ end
302
+
303
+ #
304
+ # Base class for parsed items from a query response.
305
+ #
306
+ class Item
307
+
308
+ #
309
+ # Constructor
310
+ #
311
+ # ==== Parameters
312
+ #
313
+ # item<Hash>:: The parsed item in the response. This may be a show, episode or playlist item.
314
+ #
315
+ def initialize(item)
316
+ super()
317
+ @item = item
318
+ end
319
+
320
+ #
321
+ # Explcitly declare to avoid <tt>warning: Object#id will be deprecated; use Object#object_id</tt>.
322
+ #
323
+ # ==== Parameters
324
+ #
325
+ # String:: The id of the item.
326
+ #
327
+ def id
328
+ return @item["id"]
329
+ end
330
+
331
+ #
332
+ # When requesting specific items in a query it may be the case that the item specified could not
333
+ # be found. In this case the XML returned looks something like the following for the item:
334
+ #
335
+ # <id>adfadsfasdf</id>
336
+ # <error>
337
+ # <code>6</code>
338
+ # <message>Show not found</message>
339
+ # </error>
340
+ #
341
+ # Therefore, this method allows the caller to check if the item actually exists before trying to pull
342
+ # out other properties that will result in an exception. You really only need to use this method when
343
+ # you make a query request with IDs specified.
344
+ #
345
+ # ==== Returns
346
+ #
347
+ # Boolean:: <tt>true</tt> if the item was found and requests for other attributes will succeed.
348
+ #
349
+ def exists?
350
+ return @item["error"].nil?
351
+ end
352
+
353
+ #
354
+ # Gets the list of thumbnails for this item.
355
+ #
356
+ # ==== Returns
357
+ #
358
+ # Array:: An array of <tt>Episodic::Platform::ThumbnailItem</tt> objects.
359
+ #
360
+ def thumbnails
361
+ @thumbnails ||= nested_items("thumbnails", "thumbnail", ThumbnailItem)
362
+ return @thumbnails
363
+ end
364
+
365
+ #
366
+ # Gets the list of players for this item.
367
+ #
368
+ # ==== Returns
369
+ #
370
+ # Array:: An array of <tt>Episodic::Platform::PlayerItem</tt> objects.
371
+ #
372
+ def players
373
+ @players ||= nested_items("players", "player", PlayerItem)
374
+ return @players
375
+ end
376
+
377
+ #
378
+ # Overridden to pull properties from the item.
379
+ #
380
+ def method_missing(method_sym, *arguments, &block)
381
+ method_name = method_sym.to_s
382
+
383
+ value = @item[method_name]
384
+
385
+ # Dates are always in UTC
386
+ if (value && date_fields.include?(method_sym))
387
+ return value.empty? ? nil : Time.parse("#{value} +0000")
388
+ elsif (value && boolean_fields.include?(method_sym))
389
+ return @item[method_sym.to_s] == "true"
390
+ elsif (value && integer_fields.include?(method_sym))
391
+ return value.empty? ? nil : value.to_i
392
+ end
393
+
394
+ return value && value.empty? ? nil : value
395
+ end
396
+
397
+ #
398
+ # Always return <tt>true</tt>.
399
+ #
400
+ def respond_to?(symbol, include_private = false)
401
+ return true
402
+ end
403
+
404
+ protected
405
+
406
+ #
407
+ # Helper method to pull out nested items.
408
+ #
409
+ # ==== Parameters
410
+ #
411
+ # group_name<String>:: This is something like "episodes".
412
+ # element_name<String>:: This is something like "episode".
413
+ # clazz<Class>:: This is the class of the item to create (i.e. EpisodeItem)
414
+ #
415
+ # ==== Returns
416
+ #
417
+ # Array:: An array of items of type <tt>clazz</tt>
418
+ #
419
+ def nested_items group_name, element_name, clazz
420
+ if (@item[group_name] && @item[group_name][element_name])
421
+ return @item[group_name][element_name].collect {|v| clazz.new(v)}
422
+ else
423
+ return []
424
+ end
425
+ end
426
+
427
+ #
428
+ # Should be overridden by subclasses to provide a list of fields that should
429
+ # be converted to a <tt>Time</tt> object.
430
+ #
431
+ # ==== Returns
432
+ #
433
+ # Array:: A list of field names as symbols.
434
+ #
435
+ def date_fields
436
+ return []
437
+ end
438
+
439
+ #
440
+ # Should be overridden by subclasses to provide a list of fields that should
441
+ # be converted to a <tt>Boolean</tt> object.
442
+ #
443
+ # ==== Returns
444
+ #
445
+ # Array:: A list of field names as symbols.
446
+ #
447
+ def boolean_fields
448
+ return []
449
+ end
450
+
451
+ #
452
+ # Should be overridden by subclasses to provide a list of fields that should
453
+ # be converted to a <tt>Integer</tt> object.
454
+ #
455
+ # ==== Returns
456
+ #
457
+ # Array:: A list of field names as symbols.
458
+ #
459
+ def integer_fields
460
+ return []
461
+ end
462
+ end
463
+
464
+ #
465
+ # Represents a show from a list of shows returned from a call to <tt>Episodic::Platform::QueryMethods.shows</tt>.
466
+ #
467
+ class ShowItem < Item
468
+ end
469
+
470
+ #
471
+ # Represents a episode from a list of episodes returned from a call to <tt>Episodic::Platform::QueryMethods.episodes</tt>.
472
+ #
473
+ class EpisodeItem < Item
474
+
475
+ #
476
+ # Gets the list of downloads for this item.
477
+ #
478
+ # ==== Returns
479
+ #
480
+ # Array:: An array of <tt>Episodic::Platform::DownloadItem</tt> objects.
481
+ #
482
+ def downloads
483
+ @downloads ||= nested_items("downloads", "download", DownloadItem)
484
+ return @downloads
485
+ end
486
+
487
+ #
488
+ # Gets the list of custom fields for this item.
489
+ #
490
+ # ==== Returns
491
+ #
492
+ # Array:: An array of <tt>Episodic::Platform::CustomItem</tt> objects.
493
+ #
494
+ def custom_fields
495
+ @custom_fields ||= nested_items("custom_fields", "field", CustomFieldItem)
496
+ return @custom_fields
497
+ end
498
+
499
+ #
500
+ # Gets the list of playlists for this item.
501
+ #
502
+ # ==== Returns
503
+ #
504
+ # Array:: An array of <tt>Episodic::Platform::EpisodePlaylistItem</tt> objects.
505
+ #
506
+ def playlists
507
+ @playlists ||= nested_items("playlists", "playlist", EpisodePlaylistItem)
508
+ return @playlists
509
+ end
510
+
511
+ #
512
+ # Provides a list of fields that are actually dates.
513
+ #
514
+ # ==== Returns
515
+ #
516
+ # Array:: A list of field names as symbols.
517
+ #
518
+ def date_fields
519
+ return [:air_date, :off_air_date]
520
+ end
521
+
522
+ end
523
+
524
+ #
525
+ # Represents a playlist from a list of playlists returned from a call to <tt>Episodic::Platform::QueryMethods.playlists</tt>.
526
+ #
527
+ class PlaylistItem < Item
528
+
529
+ #
530
+ # Gets the list of custom fields for this item.
531
+ #
532
+ # ==== Returns
533
+ #
534
+ # Array:: An array of <tt>Episodic::Platform::CustomItem</tt> objects.
535
+ #
536
+ def custom_fields
537
+ @custom_fields ||= nested_items("custom_fields", "field", CustomFieldItem)
538
+ return @custom_fields
539
+ end
540
+
541
+ #
542
+ # Gets the list of episodes for this item.
543
+ #
544
+ # ==== Returns
545
+ #
546
+ # Array:: An array of <tt>Episodic::Platform::PlaylistEpisodeItem</tt> objects.
547
+ #
548
+ def episodes
549
+ @episodes ||= nested_items("episodes", "episode", PlaylistEpisodeItem)
550
+ return @episodes
551
+ end
552
+
553
+ #
554
+ # Provides a list of fields that are actually dates.
555
+ #
556
+ # ==== Returns
557
+ #
558
+ # Array:: A list of field names as symbols.
559
+ #
560
+ def date_fields
561
+ return [:created_at]
562
+ end
563
+ end
564
+
565
+ #
566
+ # Represents a thumbnail element in a response.
567
+ #
568
+ class ThumbnailItem < Item
569
+
570
+ #
571
+ # Since the URL is stored in the element content we need to explicitly define
572
+ # this method to get the URL for a thumbnail.
573
+ #
574
+ # ==== Returns
575
+ #
576
+ # String:: The URL to the thumbnail.
577
+ #
578
+ def url
579
+ return @item["content"]
580
+ end
581
+
582
+ end
583
+
584
+ #
585
+ # Represents a player element in a response.
586
+ #
587
+ class PlayerItem < Item
588
+
589
+ #
590
+ # Provides a list of fields that are actually dates.
591
+ #
592
+ # ==== Returns
593
+ #
594
+ # Array:: A list of field names as symbols.
595
+ #
596
+ def boolean_fields
597
+ return [:default]
598
+ end
599
+
600
+ end
601
+
602
+ #
603
+ # Represents a download element in a response.
604
+ #
605
+ class DownloadItem < Item
606
+
607
+ #
608
+ # Get the url for the downloadable file.
609
+ #
610
+ # ==== Returns
611
+ #
612
+ # String:: The URL
613
+ #
614
+ def url
615
+ return @item["url"].first
616
+ end
617
+
618
+ end
619
+
620
+ #
621
+ # Represents a playlist element in an episodes response.
622
+ #
623
+ class EpisodePlaylistItem < Item
624
+
625
+ #
626
+ # Provides a list of fields that are actually integers.
627
+ #
628
+ # ==== Returns
629
+ #
630
+ # Array:: A list of field names as symbols.
631
+ #
632
+ def integer_fields
633
+ return [:position]
634
+ end
635
+
636
+ end
637
+
638
+ #
639
+ # Represents an episode element in a playlist response.
640
+ #
641
+ class PlaylistEpisodeItem < Item
642
+
643
+ #
644
+ # Provides a list of fields that are actually integers.
645
+ #
646
+ # ==== Returns
647
+ #
648
+ # Array:: A list of field names as symbols.
649
+ #
650
+ def integer_fields
651
+ return [:position]
652
+ end
653
+
654
+ end
655
+
656
+ #
657
+ # Represents a custom field element returned from an episodes or playlists request.
658
+ #
659
+ class CustomFieldItem < Item
660
+
661
+ #
662
+ # Get the values for this field. Values are always returned as strings except when
663
+ # the type is <tt>external_select</tt> then it is an array or two element arrays with the
664
+ # external id and external value respectively.
665
+ #
666
+ # ==== Returns
667
+ #
668
+ # Array:: In most cases this will be a single element array.
669
+ #
670
+ def values
671
+
672
+ if (@values.nil?)
673
+ @values = []
674
+ _values = @item["value"]
675
+ unless (_values.is_a?(Array))
676
+ _values = [_values]
677
+ end
678
+ _values.compact.each do |v|
679
+ if (v.is_a?(Hash))
680
+ @values << [v["id"].strip, v["content"].strip]
681
+ else
682
+ @values << v.strip
683
+ end
684
+ end
685
+ end
686
+
687
+ return @values
688
+ end
689
+
690
+ #
691
+ # Explicitly declare to avoid <tt>warning: Object#type is deprecated; use Object#class</tt>.
692
+ #
693
+ def type
694
+ return @item["type"]
695
+ end
696
+
697
+ #
698
+ # Provides a list of fields that are actually integers.
699
+ #
700
+ # ==== Returns
701
+ #
702
+ # Array:: A list of field names as symbols.
703
+ #
704
+ def integer_fields
705
+ return [:position]
706
+ end
707
+
708
+ #
709
+ # Provides a list of fields that are actually dates.
710
+ #
711
+ # ==== Returns
712
+ #
713
+ # Array:: A list of field names as symbols.
714
+ #
715
+ def boolean_fields
716
+ return [:required]
717
+ end
718
+ end
719
+ end
720
+
721
+ end