wsc_sdk 1.3.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 (265) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +146 -0
  3. data/.circleci/docker/build/Dockerfile +3 -0
  4. data/.circleci/helpers/add_preamble.rb +29 -0
  5. data/.circleci/helpers/build_docs.sh +5 -0
  6. data/.circleci/helpers/build_gem.sh +5 -0
  7. data/.circleci/helpers/debundle-context.sh +14 -0
  8. data/.circleci/helpers/finalize_release.sh +24 -0
  9. data/.circleci/helpers/publish_docs.sh +10 -0
  10. data/.circleci/helpers/release_gem.sh +8 -0
  11. data/.circleci/helpers/setup.sh +11 -0
  12. data/.circleci/helpers/setup_aws.sh +13 -0
  13. data/.circleci/helpers/setup_gem.sh +2 -0
  14. data/.circleci/helpers/setup_git.sh +27 -0
  15. data/.circleci/helpers/setup_rubygems.sh +15 -0
  16. data/.circleci/helpers/test_integration.sh +12 -0
  17. data/.circleci/helpers/test_unit.sh +6 -0
  18. data/.circleci/jobs/publish-production.sh +17 -0
  19. data/.circleci/jobs/publish-staging.sh +17 -0
  20. data/.circleci/jobs/release-production.sh +21 -0
  21. data/.circleci/jobs/test-integration.sh +9 -0
  22. data/.circleci/jobs/test-unit.sh +9 -0
  23. data/.circleci/tag_repo.rb +46 -0
  24. data/.gitignore +28 -0
  25. data/.rspec +2 -0
  26. data/.yard/config +2 -0
  27. data/.yard/template/default/fulldoc/html/css/custom.css +151 -0
  28. data/.yard/template/default/layout/html/footer.erb +0 -0
  29. data/.yard/template/default/layout/html/headers.erb +10 -0
  30. data/.yard/template/default/layout/html/layout.erb +45 -0
  31. data/.yard/template/default/layout/html/setup.rb +24 -0
  32. data/.yardopts +1 -0
  33. data/CODE_OF_CONDUCT.md +74 -0
  34. data/Gemfile +6 -0
  35. data/Gemfile.lock +99 -0
  36. data/LICENSE.txt +28 -0
  37. data/README.md +397 -0
  38. data/Rakefile +2 -0
  39. data/bin/console +14 -0
  40. data/bin/setup +8 -0
  41. data/doc/Hash.html +291 -0
  42. data/doc/WscSdk.html +570 -0
  43. data/doc/WscSdk/ApiResponse.html +242 -0
  44. data/doc/WscSdk/Attributes.html +128 -0
  45. data/doc/WscSdk/Attributes/Mode.html +191 -0
  46. data/doc/WscSdk/Attributes/Type.html +389 -0
  47. data/doc/WscSdk/Client.html +2677 -0
  48. data/doc/WscSdk/Configuration.html +595 -0
  49. data/doc/WscSdk/Endpoint.html +2974 -0
  50. data/doc/WscSdk/Endpoints.html +141 -0
  51. data/doc/WscSdk/Endpoints/CustomStreamTargets.html +383 -0
  52. data/doc/WscSdk/Endpoints/LiveStreams.html +197 -0
  53. data/doc/WscSdk/Endpoints/OutputStreamTargets.html +180 -0
  54. data/doc/WscSdk/Endpoints/Outputs.html +180 -0
  55. data/doc/WscSdk/Endpoints/StreamTargets.html +446 -0
  56. data/doc/WscSdk/Endpoints/Transcoders.html +197 -0
  57. data/doc/WscSdk/Endpoints/UllStreamTargets.html +383 -0
  58. data/doc/WscSdk/Endpoints/WowzaStreamTargets.html +383 -0
  59. data/doc/WscSdk/Enum.html +225 -0
  60. data/doc/WscSdk/Enums.html +321 -0
  61. data/doc/WscSdk/Enums/BillingMode.html +188 -0
  62. data/doc/WscSdk/Enums/BroadcastLocation.html +396 -0
  63. data/doc/WscSdk/Enums/BufferSize.html +301 -0
  64. data/doc/WscSdk/Enums/ClosedCaptionType.html +221 -0
  65. data/doc/WscSdk/Enums/CustomProvider.html +252 -0
  66. data/doc/WscSdk/Enums/DeliveryMethod.html +188 -0
  67. data/doc/WscSdk/Enums/DeliveryType.html +188 -0
  68. data/doc/WscSdk/Enums/Encoder.html +460 -0
  69. data/doc/WscSdk/Enums/Errors.html +555 -0
  70. data/doc/WscSdk/Enums/IdleTimeout.html +398 -0
  71. data/doc/WscSdk/Enums/ImagePosition.html +220 -0
  72. data/doc/WscSdk/Enums/ModelMode.html +175 -0
  73. data/doc/WscSdk/Enums/ModelType.html +373 -0
  74. data/doc/WscSdk/Enums/PlayerType.html +188 -0
  75. data/doc/WscSdk/Enums/Protocol.html +204 -0
  76. data/doc/WscSdk/Enums/TargetDeliveryProtocol.html +188 -0
  77. data/doc/WscSdk/Enums/TranscoderType.html +188 -0
  78. data/doc/WscSdk/Enums/UserRegion.html +383 -0
  79. data/doc/WscSdk/Enums/WowzaProvider.html +188 -0
  80. data/doc/WscSdk/Errors.html +683 -0
  81. data/doc/WscSdk/Loggable.html +346 -0
  82. data/doc/WscSdk/Model.html +3316 -0
  83. data/doc/WscSdk/ModelList.html +442 -0
  84. data/doc/WscSdk/ModelTemplate.html +267 -0
  85. data/doc/WscSdk/Models.html +141 -0
  86. data/doc/WscSdk/Models/CustomStreamTarget.html +192 -0
  87. data/doc/WscSdk/Models/Error.html +351 -0
  88. data/doc/WscSdk/Models/LiveStream.html +601 -0
  89. data/doc/WscSdk/Models/LiveStreamConnectionCode.html +192 -0
  90. data/doc/WscSdk/Models/LiveStreamState.html +200 -0
  91. data/doc/WscSdk/Models/LiveStreamStats.html +200 -0
  92. data/doc/WscSdk/Models/LiveStreamThumbnailUrl.html +200 -0
  93. data/doc/WscSdk/Models/Output.html +294 -0
  94. data/doc/WscSdk/Models/OutputStreamTarget.html +274 -0
  95. data/doc/WscSdk/Models/StreamTarget.html +273 -0
  96. data/doc/WscSdk/Models/Transcoder.html +793 -0
  97. data/doc/WscSdk/Models/TranscoderBooleanStat.html +278 -0
  98. data/doc/WscSdk/Models/TranscoderConnectionCode.html +192 -0
  99. data/doc/WscSdk/Models/TranscoderFloatStat.html +278 -0
  100. data/doc/WscSdk/Models/TranscoderIntegerStat.html +278 -0
  101. data/doc/WscSdk/Models/TranscoderState.html +196 -0
  102. data/doc/WscSdk/Models/TranscoderStats.html +196 -0
  103. data/doc/WscSdk/Models/TranscoderStreamTargetState.html +192 -0
  104. data/doc/WscSdk/Models/TranscoderStringStat.html +278 -0
  105. data/doc/WscSdk/Models/TranscoderThumbnailUrl.html +196 -0
  106. data/doc/WscSdk/Models/UllStreamTarget.html +360 -0
  107. data/doc/WscSdk/Models/WowzaStreamTarget.html +380 -0
  108. data/doc/WscSdk/Pagination.html +1277 -0
  109. data/doc/WscSdk/Schema.html +861 -0
  110. data/doc/WscSdk/SchemaAttribute.html +2400 -0
  111. data/doc/WscSdk/Templates.html +141 -0
  112. data/doc/WscSdk/Templates/CustomStreamTarget.html +1045 -0
  113. data/doc/WscSdk/Templates/LiveStream.html +1432 -0
  114. data/doc/WscSdk/Templates/Output.html +829 -0
  115. data/doc/WscSdk/Templates/Transcoder.html +699 -0
  116. data/doc/WscSdk/Templates/UllStreamTarget.html +411 -0
  117. data/doc/WscSdk/Templates/WowzaStreamTarget.html +447 -0
  118. data/doc/WscSdk/TranscoderSharedMethods.html +1113 -0
  119. data/doc/_index.html +705 -0
  120. data/doc/class_list.html +51 -0
  121. data/doc/css/bootstrap.css +5 -0
  122. data/doc/css/common.css +1 -0
  123. data/doc/css/custom.css +151 -0
  124. data/doc/css/full_list.css +58 -0
  125. data/doc/css/style.css +496 -0
  126. data/doc/file.README.html +570 -0
  127. data/doc/file_list.html +56 -0
  128. data/doc/frames.html +17 -0
  129. data/doc/images/wsc-ruby-1800x400.png +0 -0
  130. data/doc/index.html +570 -0
  131. data/doc/js/app.js +292 -0
  132. data/doc/js/full_list.js +216 -0
  133. data/doc/js/jquery.js +4 -0
  134. data/doc/method_list.html +1731 -0
  135. data/doc/top-level-namespace.html +182 -0
  136. data/examples/client.rb +40 -0
  137. data/examples/helpers.rb +100 -0
  138. data/examples/live_streams/create.rb +39 -0
  139. data/examples/live_streams/delete.rb +32 -0
  140. data/examples/live_streams/find.rb +22 -0
  141. data/examples/live_streams/flood.rb +126 -0
  142. data/examples/live_streams/list.rb +24 -0
  143. data/examples/live_streams/regenerate_connection_code.rb +29 -0
  144. data/examples/live_streams/reset.rb +32 -0
  145. data/examples/live_streams/reset_and_wait.rb +51 -0
  146. data/examples/live_streams/start.rb +33 -0
  147. data/examples/live_streams/start_and_wait.rb +51 -0
  148. data/examples/live_streams/state.rb +33 -0
  149. data/examples/live_streams/stats.rb +43 -0
  150. data/examples/live_streams/stop.rb +33 -0
  151. data/examples/live_streams/stop_and_wait.rb +51 -0
  152. data/examples/live_streams/thumbnail_url.rb +46 -0
  153. data/examples/live_streams/update.rb +43 -0
  154. data/examples/live_streams/workflow.rb +165 -0
  155. data/examples/output_stream_targets/create.rb +56 -0
  156. data/examples/output_stream_targets/delete.rb +45 -0
  157. data/examples/output_stream_targets/find.rb +37 -0
  158. data/examples/output_stream_targets/list.rb +36 -0
  159. data/examples/output_stream_targets/update.rb +56 -0
  160. data/examples/outputs/create.rb +49 -0
  161. data/examples/outputs/delete.rb +39 -0
  162. data/examples/outputs/find.rb +31 -0
  163. data/examples/outputs/list.rb +29 -0
  164. data/examples/outputs/update.rb +50 -0
  165. data/examples/stream_targets/custom/create.rb +42 -0
  166. data/examples/stream_targets/custom/delete.rb +31 -0
  167. data/examples/stream_targets/custom/find.rb +23 -0
  168. data/examples/stream_targets/custom/list.rb +24 -0
  169. data/examples/stream_targets/custom/update.rb +43 -0
  170. data/examples/stream_targets/list.rb +24 -0
  171. data/examples/stream_targets/ull/create.rb +41 -0
  172. data/examples/stream_targets/ull/delete.rb +31 -0
  173. data/examples/stream_targets/ull/find.rb +23 -0
  174. data/examples/stream_targets/ull/list.rb +24 -0
  175. data/examples/stream_targets/ull/update.rb +43 -0
  176. data/examples/stream_targets/wowza/create.rb +42 -0
  177. data/examples/stream_targets/wowza/delete.rb +31 -0
  178. data/examples/stream_targets/wowza/find.rb +23 -0
  179. data/examples/stream_targets/wowza/list.rb +23 -0
  180. data/examples/stream_targets/wowza/update.rb +43 -0
  181. data/examples/transcoders/create.rb +39 -0
  182. data/examples/transcoders/delete.rb +31 -0
  183. data/examples/transcoders/find.rb +23 -0
  184. data/examples/transcoders/list.rb +24 -0
  185. data/examples/transcoders/reset.rb +32 -0
  186. data/examples/transcoders/reset_and_wait.rb +48 -0
  187. data/examples/transcoders/start.rb +33 -0
  188. data/examples/transcoders/start_and_wait.rb +50 -0
  189. data/examples/transcoders/state.rb +33 -0
  190. data/examples/transcoders/stats.rb +43 -0
  191. data/examples/transcoders/stop.rb +33 -0
  192. data/examples/transcoders/stop_and_wait.rb +50 -0
  193. data/examples/transcoders/thumbnail_url.rb +46 -0
  194. data/examples/transcoders/update.rb +43 -0
  195. data/images/wsc-ruby-1800x400.png +0 -0
  196. data/lib/wsc_sdk.rb +81 -0
  197. data/lib/wsc_sdk/client.rb +417 -0
  198. data/lib/wsc_sdk/configuration.rb +21 -0
  199. data/lib/wsc_sdk/constants.rb +29 -0
  200. data/lib/wsc_sdk/endpoint.rb +492 -0
  201. data/lib/wsc_sdk/endpoints/custom_stream_targets.rb +44 -0
  202. data/lib/wsc_sdk/endpoints/live_streams.rb +34 -0
  203. data/lib/wsc_sdk/endpoints/output_stream_targets.rb +17 -0
  204. data/lib/wsc_sdk/endpoints/outputs.rb +17 -0
  205. data/lib/wsc_sdk/endpoints/stream_targets.rb +45 -0
  206. data/lib/wsc_sdk/endpoints/transcoders.rb +38 -0
  207. data/lib/wsc_sdk/endpoints/ull_stream_targets.rb +44 -0
  208. data/lib/wsc_sdk/endpoints/wowza_stream_targets.rb +44 -0
  209. data/lib/wsc_sdk/enums.rb +31 -0
  210. data/lib/wsc_sdk/enums/billing_mode.rb +20 -0
  211. data/lib/wsc_sdk/enums/broadcast_location.rb +58 -0
  212. data/lib/wsc_sdk/enums/buffer_size.rb +41 -0
  213. data/lib/wsc_sdk/enums/closed_caption_type.rb +26 -0
  214. data/lib/wsc_sdk/enums/custom_provider.rb +32 -0
  215. data/lib/wsc_sdk/enums/delivery_method.rb +20 -0
  216. data/lib/wsc_sdk/enums/delivery_type.rb +20 -0
  217. data/lib/wsc_sdk/enums/encoder.rb +71 -0
  218. data/lib/wsc_sdk/enums/idle_timeout.rb +50 -0
  219. data/lib/wsc_sdk/enums/image_position.rb +26 -0
  220. data/lib/wsc_sdk/enums/player_type.rb +20 -0
  221. data/lib/wsc_sdk/enums/protocol.rb +23 -0
  222. data/lib/wsc_sdk/enums/target_delivery_protocol.rb +20 -0
  223. data/lib/wsc_sdk/enums/transcoder_type.rb +20 -0
  224. data/lib/wsc_sdk/enums/wowza_provider.rb +20 -0
  225. data/lib/wsc_sdk/errors.rb +115 -0
  226. data/lib/wsc_sdk/model.rb +515 -0
  227. data/lib/wsc_sdk/model_list.rb +42 -0
  228. data/lib/wsc_sdk/model_template.rb +27 -0
  229. data/lib/wsc_sdk/models/custom_stream_target.rb +34 -0
  230. data/lib/wsc_sdk/models/error.rb +53 -0
  231. data/lib/wsc_sdk/models/live_stream.rb +130 -0
  232. data/lib/wsc_sdk/models/live_stream_connection_code.rb +31 -0
  233. data/lib/wsc_sdk/models/live_stream_state.rb +20 -0
  234. data/lib/wsc_sdk/models/live_stream_stats.rb +20 -0
  235. data/lib/wsc_sdk/models/live_stream_thumbnail_url.rb +20 -0
  236. data/lib/wsc_sdk/models/output.rb +61 -0
  237. data/lib/wsc_sdk/models/output_stream_target.rb +37 -0
  238. data/lib/wsc_sdk/models/stream_target.rb +29 -0
  239. data/lib/wsc_sdk/models/transcoder.rb +135 -0
  240. data/lib/wsc_sdk/models/transcoder_boolean_stat.rb +41 -0
  241. data/lib/wsc_sdk/models/transcoder_connection_code.rb +29 -0
  242. data/lib/wsc_sdk/models/transcoder_float_stat.rb +40 -0
  243. data/lib/wsc_sdk/models/transcoder_integer_stat.rb +40 -0
  244. data/lib/wsc_sdk/models/transcoder_state.rb +31 -0
  245. data/lib/wsc_sdk/models/transcoder_stats.rb +51 -0
  246. data/lib/wsc_sdk/models/transcoder_stream_target_state.rb +29 -0
  247. data/lib/wsc_sdk/models/transcoder_string_stat.rb +40 -0
  248. data/lib/wsc_sdk/models/transcoder_thumbnail_url.rb +29 -0
  249. data/lib/wsc_sdk/models/ull_stream_target.rb +54 -0
  250. data/lib/wsc_sdk/models/wowza_stream_target.rb +60 -0
  251. data/lib/wsc_sdk/modules/api_response.rb +24 -0
  252. data/lib/wsc_sdk/modules/loggable.rb +44 -0
  253. data/lib/wsc_sdk/modules/transcoder_shared_methods.rb +221 -0
  254. data/lib/wsc_sdk/pagination.rb +89 -0
  255. data/lib/wsc_sdk/schema.rb +140 -0
  256. data/lib/wsc_sdk/schema_attribute.rb +349 -0
  257. data/lib/wsc_sdk/templates/custom_stream_target.rb +154 -0
  258. data/lib/wsc_sdk/templates/live_stream.rb +234 -0
  259. data/lib/wsc_sdk/templates/output.rb +133 -0
  260. data/lib/wsc_sdk/templates/transcoder.rb +97 -0
  261. data/lib/wsc_sdk/templates/ull_stream_target.rb +49 -0
  262. data/lib/wsc_sdk/templates/wowza_stream_target.rb +57 -0
  263. data/lib/wsc_sdk/version.rb +7 -0
  264. data/wsc_sdk.gemspec +48 -0
  265. metadata +460 -0
@@ -0,0 +1,515 @@
1
+ ####> This code and all components © 2015 – 2019 Wowza Media Systems, LLC. All rights reserved.
2
+ ####> This code is licensed pursuant to the BSD 3-Clause License.
3
+
4
+ require 'wsc_sdk/modules/api_response'
5
+ require 'wsc_sdk/modules/loggable'
6
+ require 'wsc_sdk/schema'
7
+ require 'wsc_sdk/schema_attribute'
8
+
9
+ module WscSdk
10
+
11
+ # Module for model definitions.
12
+ module Models
13
+ end
14
+
15
+ # Base class for defining model schemas and managing inbound/outbound model
16
+ # data.
17
+ #
18
+ class Model
19
+ include WscSdk::ApiResponse
20
+ include WscSdk::Loggable
21
+
22
+ # @overload attributes
23
+ # A hash of attributes and values for the model
24
+ #
25
+ # *NOTE:* The attributes accessor directly accesses the attributes
26
+ # for a model. This is okay for reading data out of a model, but
27
+ # data assignment should be done using the getter
28
+ # (model.attribute) and setter (model.attribute=value) methods
29
+ # that are built into the model. Otherwise you will be bypassing
30
+ # the structures necessary to validate the data, which may
31
+ # generate unwanted outcomes.
32
+ attr_reader :attributes
33
+
34
+ # @overload errors
35
+ # A hash of fields and messages that indicates validation errors
36
+ # for the model. Use `model.valid?` if the response is false,
37
+ # this hash will contain the information necessary to fix the
38
+ # concerns.
39
+ attr_reader :errors
40
+
41
+ # @overload endpoint
42
+ # The endpoint that generated the model.
43
+ attr_reader :endpoint
44
+
45
+ # @overload changes
46
+ # An array of fields that have changed since the model was last
47
+ # saved to the API.
48
+ attr_reader :changes
49
+
50
+ # @overload partial_data
51
+ # Determines if the model contains a partial or complete dataset.
52
+ attr_reader :partial_data
53
+
54
+ # @overload data_mode
55
+ # Determines what mode the data is being ingested/accesed in.
56
+ attr_reader :data_mode
57
+
58
+ # Create a new model instance.
59
+ #
60
+ # @param endpoint [WscSdk::Endpoint]
61
+ # The endpoint instance that generated the model.
62
+ #
63
+ # @param attributes [Hash]
64
+ # A hash of attribute values to assign to the model.
65
+ #
66
+ def initialize(endpoint, attributes={})
67
+ @endpoint = endpoint
68
+ @changes = []
69
+ @partial_data = false
70
+ @data_mode = :access
71
+ initialize_attributes
72
+ ingest_attributes(attributes, write_to_read_only: true, mark_clean: true)
73
+ @errors = nil
74
+ @dirty = false
75
+ end
76
+
77
+
78
+ #---------------------------------------------------------------------------
79
+ # _ _ _ _ _ _
80
+ # /_\| |_| |_ _ _(_) |__ _ _| |_ ___ ___
81
+ # / _ \ _| _| '_| | '_ \ || | _/ -_|_-<
82
+ # /_/ \_\__|\__|_| |_|_.__/\_,_|\__\___/__/
83
+ #
84
+ #---------------------------------------------------------------------------
85
+
86
+ # Get the current schema definition
87
+ #
88
+ # @return [WscSdk::Schema]
89
+ #
90
+ def schema
91
+ self.class.schema
92
+ end
93
+
94
+ # Get the value of the primary key attribute.
95
+ #
96
+ # @return [Any]
97
+ # The value of the primary key
98
+ #
99
+ def primary_key
100
+ @attributes[self.primary_key_attribute]
101
+ end
102
+
103
+ # Get the name of the attribute that represents the primary key of the
104
+ # model.
105
+ #
106
+ # @return [Symbol]
107
+ # The name of the primary key field.
108
+ #
109
+ def primary_key_attribute
110
+ :id
111
+ end
112
+
113
+ # Clear the primary key value.
114
+ #
115
+ # This can be used to create a completely new instance of a model's data
116
+ #
117
+ def clear_primary_key
118
+ @attributes[self.primary_key_attribute] = nil
119
+ end
120
+
121
+ # Build the attributes hash from the schema definitions.
122
+ #
123
+ # This is a non-destructive process, so if the attributes are already
124
+ # established and have values, then nothing will happen to them.
125
+ #
126
+ def initialize_attributes()
127
+ @attributes ||= {}
128
+ merged_attributes = {}
129
+ defaults = self.class.schema.defaults(self)
130
+
131
+ # Merge the defaults in where attributes don't have a value defined.
132
+ defaults.each do |name, value|
133
+ merged_attributes[name] = attributes[name] || value
134
+ end
135
+ @attributes = merged_attributes
136
+ end
137
+
138
+ # Load data into the attributes hash and ensure that it meets the
139
+ # requirements of the schema.
140
+ #
141
+ # @param attributes [Hash]
142
+ # The data to load into the attributes hash.
143
+ #
144
+ # @param options [Hash]
145
+ # A hash of options
146
+ #
147
+ # @option options [Boolean] :mark_clean
148
+ # Mark the data as clean after ingesting it.
149
+ #
150
+ # @option options [Boolean] :write_to_read_only
151
+ # Allow data to be written to read only fields. This option should only
152
+ # be used by the model class, and not by users.
153
+ #
154
+ def ingest_attributes(attributes, options={})
155
+ write_to_read_only = options.fetch(:write_to_read_only, false)
156
+ mark_clean = options.fetch(:mark_clean, false)
157
+ @partial_data = options.fetch(:partial_data, false)
158
+ attributes = (attributes || {}).deep_symbolize_keys
159
+ root_key = self.class.singular_name.to_sym
160
+ attributes = attributes.has_key?(root_key) ? attributes[root_key] : attributes
161
+
162
+ attributes.each do |attribute, value|
163
+ ingest_attribute(attribute, value, options)
164
+ end
165
+ clean! if mark_clean
166
+ end
167
+
168
+ # Load an attribute value into the attributes hash and ensure that it meets
169
+ # the requirements of the schema.
170
+ #
171
+ # @param attribute [Symbol]
172
+ # The name of the attribute to ingest
173
+ #
174
+ # @param value [Any]
175
+ # The value to ingest into the attribute.
176
+ #
177
+ # @param options [Hash]
178
+ # A hash of options
179
+ #
180
+ # @option options [Boolean] :write_to_read_only
181
+ # Allow data to be written to read only fields. This option should only
182
+ # be used by the model class, and not by users.
183
+ #
184
+ def ingest_attribute(attribute, value, options={})
185
+ return unless has_attribute?(attribute)
186
+
187
+ write_to_read_only = options.fetch(:write_to_read_only, false)
188
+ attr = self.class.schema[attribute]
189
+ @data_mode = write_to_read_only ? :ingest : :access
190
+ _temp_partial_data = @partial_data
191
+ @partial_data = false
192
+ set_sym = "#{attr.attribute_name.to_s}=".to_sym
193
+
194
+ self.send(set_sym, value)
195
+
196
+ @partial_data = _temp_partial_data
197
+ end
198
+
199
+ # Determines if an attribute names exists in the schema.
200
+ #
201
+ # @param attribute [Symbol]
202
+ # The name of the attribute to determine the existence of.
203
+ #
204
+ def has_attribute?(attribute)
205
+ attributes.keys.include?(attribute)
206
+ end
207
+
208
+ # Cleans out the changes array, which means that the data is no longer
209
+ # marked as dirty.
210
+ #
211
+ def clean!
212
+ @changes = []
213
+ end
214
+
215
+ # Determines if the data is dirty or not based on whether changes have been
216
+ # marked in the changes array.
217
+ #
218
+ def dirty?
219
+ @changes.length > 0
220
+ end
221
+
222
+ # Allows you to assign a hash of data to the attributes. This approach
223
+ # uses the ingest pattern to ensure that the data being set is valid before
224
+ # applying it.
225
+ #
226
+ # @param new_attributes [Hash]
227
+ # A hash of valid, attributes
228
+ #
229
+ def attributes= new_attributes
230
+ ingest_attributes(new_attributes)
231
+ end
232
+
233
+ #---------------------------------------------------------------------------
234
+ # ___ _ _
235
+ # / __| |_ __ _| |_ ___
236
+ # \__ \ _/ _` | _/ -_)
237
+ # |___/\__\__,_|\__\___|
238
+ #
239
+ #---------------------------------------------------------------------------
240
+
241
+
242
+ # Determine if the model data is new or not.
243
+ #
244
+ # @return [Boolean]
245
+ # An indication if the model is new.
246
+ #
247
+ def new_model?
248
+ self.primary_key.nil? or self.primary_key.empty?
249
+ end
250
+
251
+ # Determine if the model data is valid and raise an exception if its not.
252
+ #
253
+ # @raise [ArgumentError]
254
+ # If the model has invalid data.
255
+ #
256
+ def valid!
257
+ raise ArgumentError.new("Invalid attribute values: #{@errors.map{ |f, m| "#{f}: #{m}"}.join(" | ")}") unless valid?
258
+ end
259
+
260
+ # Determine if the model data is valid.
261
+ #
262
+ # @return [Boolean]
263
+ # An indication if the model data is valid.
264
+ #
265
+ def valid?
266
+ validate
267
+ (errors.keys.length == 0)
268
+ end
269
+
270
+ # Validate the model data.
271
+ #
272
+ # This will populate the `.errors` hash if data is invalid.
273
+ #
274
+ def validate
275
+ @errors = {}
276
+ self.class.schema.each do |name, attribute|
277
+ value = attribute.value_or_default(self)
278
+ if attribute.required?(self) and value.nil?
279
+ add_error(name, "is required")
280
+ end
281
+
282
+ attribute.valid?(self) unless value.nil?
283
+ end
284
+ end
285
+
286
+ # Adds an error message to the errors hash.
287
+ #
288
+ # @param attribute [Symbol]
289
+ # The name of the attribute to add the error to.
290
+ #
291
+ # @param message [String]
292
+ # The message to add to the error
293
+ #
294
+ def add_error(attribute, message)
295
+ @errors[attribute] ||= []
296
+ @errors[attribute] << message
297
+ end
298
+
299
+ # Refresh the data in the model from the API.
300
+ #
301
+ # @return [WscSdk::Model]
302
+ # A copy of the model if the refresh was successful. An error model if
303
+ # the refresh was a failure.
304
+ #
305
+ def refresh
306
+ if new_model?
307
+ return WscSdk::Errors.model_does_not_exist(self.endpoint)
308
+ else
309
+ return self.endpoint.refresh(self)
310
+ end
311
+ end
312
+
313
+ # Save the data in the model to the api.
314
+ #
315
+ # If the model is new, then the endpoint create method will be called, if
316
+ # the model is not new, then the endpoint update method will be called.
317
+ #
318
+ # @return [WscSdk::Model]
319
+ # If the created/updated model is valid and returns properly from the
320
+ # endpoint.
321
+ #
322
+ # @return [Nil]
323
+ # If the created/updated model is invalid.
324
+ #
325
+ def save
326
+ result = nil
327
+ if new_model?
328
+ result = endpoint.create(self)
329
+ @attributes[self.primary_key_attribute] = result.primary_key if result.success?
330
+ elsif dirty?
331
+ result = endpoint.update(self)
332
+ else
333
+ result = self
334
+ end
335
+ clean! if result.success?
336
+ result
337
+ end
338
+
339
+ # Delete the model data from the api.
340
+ #
341
+ # @return [WscSdk::Model]
342
+ # If the created/updated model is valid and returns properly from the
343
+ # endpoint.
344
+ #
345
+ # @return [Nil]
346
+ # If the created/updated model is invalid.
347
+ #
348
+ def delete
349
+ return WscSdk::Errors.model_does_not_exist(self.endpoint) if new_model?
350
+ result = endpoint.delete(self)
351
+ if result.success?
352
+ clean!
353
+ clear_primary_key
354
+ @partial_data = false
355
+ end
356
+ return result
357
+ end
358
+
359
+ # Return the success status of the API call that generated this model.
360
+ #
361
+ # @return [Boolean]
362
+ # An indication of the status of the API call.
363
+ #
364
+ def success?
365
+ return true
366
+ end
367
+
368
+ #---------------------------------------------------------------------------
369
+ # _ ___ ___ ___ _
370
+ # /_\ | _ \_ _| | \ __ _| |_ __ _
371
+ # / _ \| _/| | | |) / _` | _/ _` |
372
+ # /_/ \_\_| |___| |___/\__,_|\__\__,_|
373
+ #
374
+ #---------------------------------------------------------------------------
375
+
376
+
377
+ # If only a part of the data was requested for the model (e.g. in a list
378
+ # endpoint), then we will request the full data set for the particular
379
+ # object and load the data into the model.
380
+ #
381
+ private def request_remaining_data
382
+ if partial_data
383
+ data_model = endpoint.find(self.id)
384
+ remaining_data = data_model.attributes.clone
385
+ ingest_attributes(remaining_data, write_to_read_only: true, mark_clean: true, partial_data: false)
386
+ end
387
+ end
388
+
389
+ # Build the request payload, or generate an exception if the data is
390
+ # not valid.
391
+ #
392
+ # @raise [ArgumenError]
393
+ # If the model has invalid data.
394
+ #
395
+ # @return [Hash]
396
+ # The properly structure request data.
397
+ #
398
+ def build_payload!
399
+ valid!
400
+ return build_payload
401
+ end
402
+
403
+ # Build the request payload.
404
+ #
405
+ # @return [Hash]
406
+ # The properly structure request data.
407
+ #
408
+ def build_payload
409
+ return nil unless valid?
410
+
411
+ model_wrapper = self.class.singular_name.to_sym
412
+ payload = {}
413
+ wrapper = payload[model_wrapper] = {}
414
+
415
+ self.schema.each do |name, attribute|
416
+ if attribute.write_access?(self)
417
+ value = attribute.value_or_default(self)
418
+ required = attribute.required?(self)
419
+
420
+ if required or !value.nil?
421
+ wrapper[name] = value
422
+ end
423
+ end
424
+ end
425
+
426
+ payload
427
+ end
428
+
429
+ #---------------------------------------------------------------------------
430
+ # __ __
431
+ # | \/ |__ _ __ _ _ ___ ___
432
+ # | |\/| / _` / _| '_/ _ (_-<
433
+ # |_| |_\__,_\__|_| \___/__/
434
+ #
435
+ #---------------------------------------------------------------------------
436
+
437
+
438
+ # Rebuilds the `primary_key_attribute` method in the class to identify an
439
+ # attribute other than the default as the primary key
440
+ #
441
+ # @param [Symbol] attribute_name
442
+ # The name of the attribute to use as the primary key.
443
+ #
444
+ def self.primary_key(attribute_name)
445
+ define_method :primary_key_attribute do
446
+ return attribute_name.to_sym
447
+ end
448
+ end
449
+
450
+ # Builds the `singular_name` static method that will return the name of the
451
+ # model in singular form.
452
+ #
453
+ def self.model_name_singular(wrapper)
454
+ define_singleton_method :singular_name do
455
+ wrapper
456
+ end
457
+ end
458
+
459
+ # Builds the `plural_name` static method that will return the name of the
460
+ # model in plural form.
461
+ #
462
+ def self.model_name_plural(wrapper)
463
+ define_singleton_method :plural_name do
464
+ wrapper
465
+ end
466
+ end
467
+
468
+ # Defines the default schema structure.
469
+ #
470
+ def self.schema
471
+ Schema.new
472
+ end
473
+
474
+ # Defines an attribute in the model schema and establishes the appropriate
475
+ # getters/setters according to its access settings.
476
+ #
477
+ def self.attribute(name, type, options={})
478
+ name = name.to_sym
479
+ accessor_name = options.fetch(:as, name).to_sym
480
+ type = type.to_sym
481
+ current_schema = self.schema
482
+ attr = current_schema.add_attribute(name, type, options)
483
+
484
+ define_singleton_method :schema do
485
+ current_schema
486
+ end
487
+
488
+ define_method accessor_name do
489
+ raise ::NoMethodError.new("the '#{accessor_name}' attribute is not currently readable") unless schema[name].read_access?(self)
490
+ current_value = @attributes[name.to_sym]
491
+ request_remaining_data if (@partial_data and current_value.nil?)
492
+ @attributes[name.to_sym]
493
+ end
494
+
495
+ set_sym = "#{accessor_name.to_s}=".to_sym
496
+ define_method(set_sym) do |value|
497
+ not_writable = ((@data_mode == :access) and (!schema[name].write_access?(self)))
498
+ if not_writable
499
+ logger.warn("Attempting to write to non-writable attribute: #{accessor_name}")
500
+ return
501
+ end
502
+ valid_type = self.class.schema.valid_type?(name, value)
503
+ if valid_type
504
+ self.attributes[name] = self.class.schema.transform_value(name, self, value)
505
+ @errors = nil
506
+ @changes << name
507
+ else
508
+ logger.warn("The attribute '#{accessor_name.to_s}' expected a(n) #{type} value but got '#{value}' [#{value.class.name}] instead!")
509
+ end
510
+ end
511
+
512
+ end
513
+
514
+ end
515
+ end