assembla_api 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/Rakefile +22 -0
  4. data/lib/assembla_api.rb +130 -0
  5. data/lib/assembla_api/api.rb +373 -0
  6. data/lib/assembla_api/api/actions.rb +58 -0
  7. data/lib/assembla_api/api/arguments.rb +248 -0
  8. data/lib/assembla_api/api/config.rb +107 -0
  9. data/lib/assembla_api/api/config/property.rb +30 -0
  10. data/lib/assembla_api/api/config/property_set.rb +119 -0
  11. data/lib/assembla_api/api/factory.rb +33 -0
  12. data/lib/assembla_api/authorization.rb +76 -0
  13. data/lib/assembla_api/client.rb +21 -0
  14. data/lib/assembla_api/client/activity.rb +30 -0
  15. data/lib/assembla_api/client/authorizations.rb +143 -0
  16. data/lib/assembla_api/client/authorizations/app.rb +98 -0
  17. data/lib/assembla_api/client/portfolio.rb +19 -0
  18. data/lib/assembla_api/client/portfolio/invitations.rb +30 -0
  19. data/lib/assembla_api/client/portfolio/spaces.rb +13 -0
  20. data/lib/assembla_api/client/portfolio/standup_reports.rb +34 -0
  21. data/lib/assembla_api/client/portfolio/tasks.rb +13 -0
  22. data/lib/assembla_api/client/portfolio/ticket_reports.rb +13 -0
  23. data/lib/assembla_api/client/portfolio/tickets.rb +13 -0
  24. data/lib/assembla_api/client/portfolio/users.rb +13 -0
  25. data/lib/assembla_api/client/spaces.rb +140 -0
  26. data/lib/assembla_api/client/spaces/documents.rb +87 -0
  27. data/lib/assembla_api/client/spaces/milestones.rb +102 -0
  28. data/lib/assembla_api/client/spaces/space_tools.rb +65 -0
  29. data/lib/assembla_api/client/spaces/space_tools/merge_requests.rb +105 -0
  30. data/lib/assembla_api/client/spaces/space_tools/merge_requests/versions.rb +41 -0
  31. data/lib/assembla_api/client/spaces/space_tools/merge_requests/versions/comments.rb +34 -0
  32. data/lib/assembla_api/client/spaces/space_tools/merge_requests/versions/votes.rb +46 -0
  33. data/lib/assembla_api/client/spaces/ssh.rb +14 -0
  34. data/lib/assembla_api/client/spaces/ssh/actions.rb +76 -0
  35. data/lib/assembla_api/client/spaces/ssh/actions/launches.rb +14 -0
  36. data/lib/assembla_api/client/spaces/ssh/keys.rb +18 -0
  37. data/lib/assembla_api/client/spaces/ssh/launches.rb +29 -0
  38. data/lib/assembla_api/client/spaces/ssh/servers.rb +63 -0
  39. data/lib/assembla_api/client/spaces/standup_away_reports.rb +41 -0
  40. data/lib/assembla_api/client/spaces/standup_reports.rb +41 -0
  41. data/lib/assembla_api/client/spaces/tags.rb +96 -0
  42. data/lib/assembla_api/client/spaces/tickets.rb +154 -0
  43. data/lib/assembla_api/client/spaces/tickets/associations.rb +57 -0
  44. data/lib/assembla_api/client/spaces/tickets/comments.rb +45 -0
  45. data/lib/assembla_api/client/spaces/tickets/custom_fields.rb +57 -0
  46. data/lib/assembla_api/client/spaces/tickets/statuses.rb +55 -0
  47. data/lib/assembla_api/client/spaces/user_roles.rb +61 -0
  48. data/lib/assembla_api/client/spaces/users.rb +11 -0
  49. data/lib/assembla_api/client/spaces/webhooks.rb +63 -0
  50. data/lib/assembla_api/client/spaces/wiki_pages.rb +78 -0
  51. data/lib/assembla_api/client/spaces/wiki_pages/versions.rb +20 -0
  52. data/lib/assembla_api/client/tasks.rb +72 -0
  53. data/lib/assembla_api/client/users.rb +49 -0
  54. data/lib/assembla_api/client/users/keys.rb +97 -0
  55. data/lib/assembla_api/configuration.rb +71 -0
  56. data/lib/assembla_api/connection.rb +66 -0
  57. data/lib/assembla_api/constants.rb +74 -0
  58. data/lib/assembla_api/core_ext/array.rb +25 -0
  59. data/lib/assembla_api/core_ext/hash.rb +92 -0
  60. data/lib/assembla_api/core_ext/ordered_hash.rb +107 -0
  61. data/lib/assembla_api/deprecation.rb +39 -0
  62. data/lib/assembla_api/error.rb +37 -0
  63. data/lib/assembla_api/error/bad_request.rb +14 -0
  64. data/lib/assembla_api/error/client_error.rb +20 -0
  65. data/lib/assembla_api/error/forbidden.rb +14 -0
  66. data/lib/assembla_api/error/internal_server_error.rb +15 -0
  67. data/lib/assembla_api/error/invalid_options.rb +18 -0
  68. data/lib/assembla_api/error/not_acceptable.rb +15 -0
  69. data/lib/assembla_api/error/not_found.rb +14 -0
  70. data/lib/assembla_api/error/required_params.rb +18 -0
  71. data/lib/assembla_api/error/service_error.rb +68 -0
  72. data/lib/assembla_api/error/service_unavailable.rb +15 -0
  73. data/lib/assembla_api/error/unauthorized.rb +15 -0
  74. data/lib/assembla_api/error/unknown_media.rb +18 -0
  75. data/lib/assembla_api/error/unknown_value.rb +18 -0
  76. data/lib/assembla_api/error/unprocessable_entity.rb +14 -0
  77. data/lib/assembla_api/error/validations.rb +18 -0
  78. data/lib/assembla_api/ext/faraday.rb +38 -0
  79. data/lib/assembla_api/jsonable.rb +18 -0
  80. data/lib/assembla_api/middleware.rb +31 -0
  81. data/lib/assembla_api/mime_type.rb +33 -0
  82. data/lib/assembla_api/normalizer.rb +25 -0
  83. data/lib/assembla_api/null_encoder.rb +25 -0
  84. data/lib/assembla_api/page_iterator.rb +142 -0
  85. data/lib/assembla_api/page_links.rb +45 -0
  86. data/lib/assembla_api/paged_request.rb +40 -0
  87. data/lib/assembla_api/pagination.rb +102 -0
  88. data/lib/assembla_api/parameter_filter.rb +32 -0
  89. data/lib/assembla_api/params_hash.rb +101 -0
  90. data/lib/assembla_api/rate_limit.rb +25 -0
  91. data/lib/assembla_api/request.rb +85 -0
  92. data/lib/assembla_api/request/basic_auth.rb +33 -0
  93. data/lib/assembla_api/request/jsonize.rb +53 -0
  94. data/lib/assembla_api/request/key_auth.rb +31 -0
  95. data/lib/assembla_api/request/oauth2.rb +42 -0
  96. data/lib/assembla_api/request/verbs.rb +60 -0
  97. data/lib/assembla_api/response.rb +28 -0
  98. data/lib/assembla_api/response/header.rb +76 -0
  99. data/lib/assembla_api/response/jsonize.rb +29 -0
  100. data/lib/assembla_api/response/mashify.rb +24 -0
  101. data/lib/assembla_api/response/raise_error.rb +18 -0
  102. data/lib/assembla_api/response/xmlize.rb +26 -0
  103. data/lib/assembla_api/response_wrapper.rb +157 -0
  104. data/lib/assembla_api/ssl_certs/cacerts.pem +2183 -0
  105. data/lib/assembla_api/utils/url.rb +59 -0
  106. data/lib/assembla_api/validations.rb +25 -0
  107. data/lib/assembla_api/validations/format.rb +24 -0
  108. data/lib/assembla_api/validations/presence.rb +30 -0
  109. data/lib/assembla_api/validations/required.rb +24 -0
  110. data/lib/assembla_api/validations/token.rb +41 -0
  111. data/lib/assembla_api/version.rb +12 -0
  112. metadata +347 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 544c0b5cf90c28355fa82a7c6705f1ac875a1ce2
4
+ data.tar.gz: 8d97d3258aa5ae4fef0838249c7230de0f00fe26
5
+ SHA512:
6
+ metadata.gz: 3068a96928b8169a1a0dce98ec74a905203b8160774e84f744649bfcc60dacd1b9d2b6a4ad920524429071c9231dc8a6fe8c9994a1a6721e123b796797c243ca
7
+ data.tar.gz: 830a2513a480adb5922289325df0c5e4527dea53284bba6422d76407899b908183174dd708e5c88131bd9b23bc9f5e8b705e903485a831152ac6085caff760dd
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Assembla
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ #RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ # spec.pattern = FileList['spec/**/*_spec.rb']
8
+ #end
9
+
10
+ FileList['tasks/**/*.rake'].each(&method(:import))
11
+
12
+ #desc 'Run all specs on CI'
13
+ #task ci: [:spec, :features, 'coveralls:push']
14
+
15
+ desc 'Load gem inside irb console'
16
+ task :console do
17
+ require 'irb'
18
+ require 'irb/completion'
19
+ require File.join(__FILE__, '../lib/assembla_api')
20
+ ARGV.clear
21
+ IRB.start
22
+ end
@@ -0,0 +1,130 @@
1
+ # encoding: utf-8
2
+
3
+ require 'faraday'
4
+ require 'assembla_api/version'
5
+ require 'assembla_api/configuration'
6
+ require 'assembla_api/constants'
7
+ require 'assembla_api/utils/url'
8
+ require 'assembla_api/connection'
9
+ require 'assembla_api/deprecation'
10
+ require 'assembla_api/core_ext/ordered_hash'
11
+ require 'assembla_api/ext/faraday'
12
+ require 'assembla_api/middleware'
13
+
14
+ module Assembla
15
+ LIBNAME = 'assembla_api'
16
+
17
+ LIBDIR = File.expand_path("../#{LIBNAME}", __FILE__)
18
+
19
+ class << self
20
+ def included(base)
21
+ base.extend ClassMethods
22
+ end
23
+
24
+ # Alias for Assembla::Client.new
25
+ #
26
+ # @param [Hash] options
27
+ # the configuration options
28
+ #
29
+ # @return [Assembla::Client]
30
+ #
31
+ # @api public
32
+ def new(options = {}, &block)
33
+ Client.new(options, &block)
34
+ end
35
+
36
+ # Default middleware stack that uses default adapter as specified
37
+ # by configuration setup
38
+ #
39
+ # @return [Proc]
40
+ #
41
+ # @api private
42
+ def default_middleware(options = {})
43
+ Middleware.default(options)
44
+ end
45
+
46
+ # Delegate to Assembla::Client
47
+ #
48
+ # @api private
49
+ def method_missing(method_name, *args, &block)
50
+ if new.respond_to?(method_name)
51
+ new.send(method_name, *args, &block)
52
+ elsif configuration.respond_to?(method_name)
53
+ Assembla.configuration.send(method_name, *args, &block)
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ def respond_to?(method_name, include_private = false)
60
+ new.respond_to?(method_name, include_private) ||
61
+ configuration.respond_to?(method_name) ||
62
+ super(method_name, include_private)
63
+ end
64
+ end
65
+
66
+ module ClassMethods
67
+
68
+ # Requires internal libraries
69
+ #
70
+ # @param [String] prefix
71
+ # the relative path prefix
72
+ # @param [Array[String]] libs
73
+ # the array of libraries to require
74
+ #
75
+ # @return [self]
76
+ def require_all(prefix, *libs)
77
+ libs.each do |lib|
78
+ require "#{File.join(prefix, lib)}"
79
+ end
80
+ end
81
+
82
+ # The client configuration
83
+ #
84
+ # @return [Configuration]
85
+ #
86
+ # @api public
87
+ def configuration
88
+ @configuration ||= Configuration.new
89
+ end
90
+
91
+ # Configure options
92
+ #
93
+ # @example
94
+ # Assembla.configure do |c|
95
+ # c.some_option = true
96
+ # end
97
+ #
98
+ # @yield the configuration block
99
+ # @yieldparam configuration [Assembla::Configuration]
100
+ # the configuration instance
101
+ #
102
+ # @return [nil]
103
+ #
104
+ # @api public
105
+ def configure
106
+ yield configuration
107
+ end
108
+ end
109
+
110
+ extend ClassMethods
111
+
112
+ require_all LIBDIR,
113
+ 'authorization',
114
+ 'validations',
115
+ 'normalizer',
116
+ 'parameter_filter',
117
+ 'api',
118
+ 'client',
119
+ 'pagination',
120
+ 'request',
121
+ 'response',
122
+ 'response_wrapper',
123
+ 'error',
124
+ 'mime_type',
125
+ 'page_links',
126
+ 'paged_request',
127
+ 'page_iterator',
128
+ 'params_hash'
129
+
130
+ end # Assembla
@@ -0,0 +1,373 @@
1
+ # encoding: utf-8
2
+
3
+ require 'assembla_api/configuration'
4
+ require 'assembla_api/mime_type'
5
+ require 'assembla_api/rate_limit'
6
+ require 'assembla_api/core_ext/hash'
7
+ require 'assembla_api/core_ext/array'
8
+ require 'assembla_api/null_encoder'
9
+
10
+ require 'assembla_api/request/verbs'
11
+
12
+ require 'assembla_api/api/actions'
13
+ require 'assembla_api/api/factory'
14
+ require 'assembla_api/api/arguments'
15
+
16
+ module Assembla
17
+ # Core class responsible for api interface operations
18
+ class API
19
+ extend Assembla::ClassMethods
20
+ include Constants
21
+ include Authorization
22
+ include MimeType
23
+ include Request::Verbs
24
+ include RateLimit
25
+
26
+ attr_reader *Assembla.configuration.property_names
27
+
28
+ attr_accessor *Validations::VALID_API_KEYS
29
+
30
+ attr_accessor :current_options
31
+
32
+ # Callback to update current configuration options
33
+ class_eval do
34
+ Assembla.configuration.property_names.each do |key|
35
+ define_method "#{key}=" do |arg|
36
+ self.instance_variable_set("@#{key}", arg)
37
+ self.current_options.merge!({:"#{key}" => arg})
38
+ end
39
+ end
40
+ end
41
+
42
+ # Create new API
43
+ #
44
+ # @api public
45
+ def initialize(options={}, &block)
46
+ setup(options)
47
+ yield_or_eval(&block) if block_given?
48
+ end
49
+
50
+ def yield_or_eval(&block)
51
+ return unless block
52
+ block.arity > 0 ? yield(self) : self.instance_eval(&block)
53
+ end
54
+
55
+ # Configure options and process basic authorization
56
+ #
57
+ # @api private
58
+ def setup(options={})
59
+ options = Assembla.configuration.fetch.merge(options)
60
+ self.current_options = options
61
+ Assembla.configuration.property_names.each do |key|
62
+ send("#{key}=", options[key])
63
+ end
64
+ process_basic_auth(options[:basic_auth])
65
+ end
66
+
67
+ # Extract login and password from basic_auth parameter
68
+ #
69
+ def process_basic_auth(auth)
70
+ case auth
71
+ when String
72
+ self.login, self.password = auth.split(':', 2)
73
+ when Hash
74
+ self.login = auth[:login]
75
+ self.password = auth[:password]
76
+ end
77
+ end
78
+
79
+ # List of before callbacks
80
+ #
81
+ # @api public
82
+ def self.before_callbacks
83
+ @before_callbacks ||= []
84
+ end
85
+
86
+ # List of after callbacks
87
+ #
88
+ # @api public
89
+ def self.after_callbacks
90
+ @after_callbacks ||= []
91
+ end
92
+
93
+ # Before request filter
94
+ #
95
+ # @api public
96
+ def self.before_request(callback, params = {})
97
+ before_callbacks << params.merge(callback: callback)
98
+ end
99
+
100
+ # After request filter
101
+ #
102
+ # @api public
103
+ def self.after_request(callback, params = {})
104
+ after_callbacks << params.merge(callback: callback)
105
+ end
106
+
107
+ class << self
108
+ attr_reader :root
109
+ alias_method :root?, :root
110
+ end
111
+
112
+ def self.root!
113
+ @root = true
114
+ end
115
+
116
+ def self.inherited(child_class)
117
+ before_callbacks.reverse_each { |callback|
118
+ child_class.before_callbacks.unshift(callback)
119
+ }
120
+ after_callbacks.reverse_each { |callback|
121
+ child_class.after_callbacks.unshift(callback)
122
+ }
123
+ extend_with_actions(child_class)
124
+ unless child_class.instance_variable_defined?(:@root)
125
+ child_class.instance_variable_set(:@root, false)
126
+ end
127
+ super
128
+ end
129
+
130
+ root!
131
+
132
+ def self.internal_methods
133
+ api = self
134
+ api = api.superclass until api.root?
135
+ api.public_instance_methods(true)
136
+ end
137
+
138
+ def self.extra_methods
139
+ ['actions']
140
+ end
141
+
142
+ # Find all the api methods that should be considred by
143
+ # request callbacks.
144
+ #
145
+ # @return [Set]
146
+ #
147
+ # @api private
148
+ def self.request_methods
149
+ @request_methods ||= begin
150
+ methods = (public_instance_methods(true) -
151
+ internal_methods +
152
+ public_instance_methods(false)).uniq.map(&:to_s)
153
+ Set.new(methods - extra_methods)
154
+ end
155
+ end
156
+
157
+ def self.clear_request_methods!
158
+ @request_methods = nil
159
+ end
160
+
161
+ def self.method_added(method_name)
162
+ method_name = method_name.to_s.gsub(/_with(out)?_callback_.*$/, '')
163
+ # Only subclasses matter
164
+ return if self.root?
165
+ return if extra_methods.include?(method_name)
166
+ # Only public methods are of interest
167
+ return unless request_methods.include?(method_name)
168
+ # Do not redefine
169
+ return if (@__methods_added ||= []).include?(method_name)
170
+
171
+ class_name = self.name.to_s.split('::').last.downcase
172
+ with_method = "#{method_name}_with_callback_#{class_name}"
173
+ without_method = "#{method_name}_without_callback_#{class_name}"
174
+
175
+ return if public_method_defined?(with_method)
176
+
177
+ [method_name, with_method, without_method].each do |met|
178
+ @__methods_added << met
179
+ end
180
+ return if public_method_defined?(with_method)
181
+
182
+ define_method(with_method) do |*args, &block|
183
+ send(:execute, without_method, *args, &block)
184
+ end
185
+ alias_method without_method, method_name
186
+ alias_method method_name, with_method
187
+ clear_request_methods!
188
+ end
189
+
190
+ # Filter callbacks based on kind
191
+ #
192
+ # @param [Symbol] kind
193
+ # one of :before or :after
194
+ #
195
+ # @return [Array[Hash]]
196
+ #
197
+ # @api private
198
+ def filter_callbacks(kind, action_name)
199
+ matched_callbacks = self.class.send("#{kind}_callbacks").select do |callback|
200
+ callback[:only].nil? || callback[:only].include?(action_name)
201
+ end
202
+ end
203
+
204
+ # Run all callbacks associated with this action
205
+ #
206
+ # @apram [Symbol] action_name
207
+ #
208
+ # @api private
209
+ def run_callbacks(action_name, &block)
210
+ filter_callbacks(:before, action_name).each { |hook| send hook[:callback] }
211
+ yield if block_given?
212
+ filter_callbacks(:after, action_name).each { |hook| send hook[:callback] }
213
+ end
214
+
215
+ # Execute action
216
+ #
217
+ # @param [Symbol] action
218
+ #
219
+ # @api private
220
+ def execute(action, *args, &block)
221
+ action_name = action.to_s.gsub(/_with(out)?_callback_.*$/, '')
222
+ result = nil
223
+ run_callbacks(action_name) do
224
+ result = send(action, *args, &block)
225
+ end
226
+ result
227
+ end
228
+
229
+ # Responds to attribute query or attribute clear
230
+ #
231
+ # @api private
232
+ def method_missing(method_name, *args, &block) # :nodoc:
233
+ case method_name.to_s
234
+ when /^(.*)\?$/
235
+ return !!send($1.to_s)
236
+ when /^clear_(.*)$/
237
+ send("#{$1.to_s}=", nil)
238
+ else
239
+ super
240
+ end
241
+ end
242
+
243
+ # Acts as setter and getter for api requests arguments parsing.
244
+ #
245
+ # Returns Arguments instance.
246
+ #
247
+ def arguments(args=(not_set = true), options={}, &block)
248
+ if not_set
249
+ @arguments
250
+ else
251
+ @arguments = Arguments.new(options.merge!(api: self)).parse(*args, &block)
252
+ end
253
+ end
254
+
255
+ # Scope for passing request required arguments.
256
+ #
257
+ def with(args)
258
+ case args
259
+ when Hash
260
+ set args
261
+ when /.*\/.*/i
262
+ user, repo = args.split('/')
263
+ set :user => user, :repo => repo
264
+ else
265
+ ::Kernel.raise ArgumentError, 'This api does not support passed in arguments'
266
+ end
267
+ end
268
+
269
+ # Set a configuration option for a given namespace
270
+ #
271
+ # @param [String] option
272
+ # @param [Object] value
273
+ # @param [Boolean] ignore_setter
274
+ #
275
+ # @return [self]
276
+ #
277
+ # @api public
278
+ def set(option, value=(not_set=true), ignore_setter=false, &block)
279
+ raise ArgumentError, 'value not set' if block and !not_set
280
+ return self if !not_set and value.nil?
281
+
282
+ if not_set
283
+ set_options option
284
+ return self
285
+ end
286
+
287
+ if respond_to?("#{option}=") and not ignore_setter
288
+ return __send__("#{option}=", value)
289
+ end
290
+
291
+ define_accessors option, value
292
+ self
293
+ end
294
+
295
+ # Defines a namespace
296
+ #
297
+ # @param [Array[Symbol]] names
298
+ # the name for the scope
299
+ #
300
+ # @return [self]
301
+ #
302
+ # @api public
303
+ def self.namespace(*names)
304
+ options = names.last.is_a?(Hash) ? names.pop : {}
305
+ names = names.map(&:to_sym)
306
+ name = names.pop
307
+ return if public_method_defined?(name)
308
+
309
+ class_name = extract_class_name(name, options)
310
+ define_method(name) do |*args, &block|
311
+ options = args.last.is_a?(Hash) ? args.pop : {}
312
+ API::Factory.new(class_name, current_options.merge(options), &block)
313
+ end
314
+ self
315
+ end
316
+
317
+ # Extracts class name from options
318
+ #
319
+ # @param [Hash] options
320
+ # @option options [String] :full_name
321
+ # the full name for the class
322
+ # @option options [Boolean] :root
323
+ # if the class is at the root or not
324
+ #
325
+ # @return [String]
326
+ #
327
+ # @api private
328
+ def self.extract_class_name(name, options)
329
+ converted = options.fetch(:full_name, name).to_s
330
+ converted = converted.split('_').map(&:capitalize).join
331
+ class_name = options.fetch(:root, false) ? '': "#{self.name}::"
332
+ class_name += converted
333
+ class_name
334
+ end
335
+
336
+ private
337
+
338
+ # Set multiple options
339
+ #
340
+ # @api private
341
+ def set_options(options)
342
+ unless options.respond_to?(:each)
343
+ raise ArgumentError, 'cannot iterate over value'
344
+ end
345
+ options.each { |key, value| set(key, value) }
346
+ end
347
+
348
+ # Define setters and getters
349
+ #
350
+ # @api private
351
+ def define_accessors(option, value)
352
+ setter = proc { |val| set option, val, true }
353
+ getter = proc { value }
354
+
355
+ define_singleton_method("#{option}=", setter) if setter
356
+ define_singleton_method(option, getter) if getter
357
+ end
358
+
359
+ # Dynamically define a method for setting request option
360
+ #
361
+ # @api private
362
+ def define_singleton_method(method_name, content=Proc.new)
363
+ (class << self; self; end).class_eval do
364
+ undef_method(method_name) if method_defined?(method_name)
365
+ if String === content
366
+ class_eval("def #{method_name}() #{content}; end")
367
+ else
368
+ define_method(method_name, &content)
369
+ end
370
+ end
371
+ end
372
+ end # API
373
+ end # Assembla