app_store_connect 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f85d306e9c8dc76fba857925802ffe5fe93ea214e38687e18456e154cd047851
4
- data.tar.gz: 57e51afffdea8202304ab9d5babac5a78b3fc2ab97a27287a2e3e58e043e5efd
3
+ metadata.gz: c2dcb0baeec6115b19cceb61065868ea2a8df22bc38ddfa7119cebc302be7ffb
4
+ data.tar.gz: ac6daafc5325d9c092d8db0e4f4540261ed70df222f930306d108fd5bf69e61b
5
5
  SHA512:
6
- metadata.gz: 12864a719bf9a8e774fe6b469ef154ca1c9f405d8f93194833c05c760abd52351264668b3f8894d9e1040bf1ba29be8a60bc2f0850ab622168af7233785485e7
7
- data.tar.gz: 82d4d4b9aa81554064e6499ac7abd861a4d697df10a113f01a980381794f62a8535fdda28cfa21951f136b9a36ff70afdbac7a790c74efb1b8fb001b187ce4ff
6
+ metadata.gz: ea23fccdf0a8484e89a51ab75b1b072162916b49b0c874e2868c94b30d8e7b45ab57ff8295f46c0a75257251ef7dce8fa3e51e09cc4a472a333d330224cedfad
7
+ data.tar.gz: d820dc77c974d603129ad684aa31b06bb79482a03600c023f33b0e6f953576e529a4b54c375b172255a676fd43832e72a00444ad3bc1344f23c1fc0761934110
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- app_store_connect (0.10.0)
5
- activesupport (~> 5.2.3)
6
- jwt (~> 2.1)
4
+ app_store_connect (0.11.0)
5
+ activesupport (>= 5.1.7)
6
+ jwt (>= 1.4)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -36,6 +36,25 @@ app_store_connect.app(id: '1234')
36
36
  app_store_connect.builds(id: '1234')
37
37
  ```
38
38
 
39
+ ### Register Device
40
+
41
+ ```ruby
42
+ app_store_connect.create_device(
43
+ name: 'Kyle Decot\'s iPhone',
44
+ udid: '...'
45
+ )
46
+ ```
47
+
48
+ ### Create Bundle ID
49
+
50
+ ```ruby
51
+ app_store_connect.create_bundle_id(
52
+ name: 'Example',
53
+ identifier: 'com.kyledecot.Example',
54
+ platform: 'IOS'
55
+ )
56
+ ```
57
+
39
58
  ## Development
40
59
 
41
60
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.require_paths = ['lib']
22
22
 
23
- spec.add_runtime_dependency 'activesupport', '~> 5.2.3'
24
- spec.add_runtime_dependency 'jwt', '~> 2.1'
23
+ spec.add_runtime_dependency 'activesupport', '>= 5.1.7'
24
+ spec.add_runtime_dependency 'jwt', '>= 1.4'
25
25
 
26
26
  spec.add_development_dependency 'bundler', '~> 2.0'
27
27
  spec.add_development_dependency 'factory_bot', '~> 5.0.2'
@@ -1,41 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'jwt'
4
-
5
- require 'app_store_connect/authorization'
6
- require 'app_store_connect/parser'
7
-
8
- require 'app_store_connect/schema'
3
+ require 'app_store_connect/client'
4
+ require 'app_store_connect/factory'
9
5
  require 'app_store_connect/object/type'
10
6
  require 'app_store_connect/object/attributes'
11
7
  require 'app_store_connect/object/properties'
12
8
  require 'app_store_connect/object/data'
13
- require 'app_store_connect/create_request'
14
- require 'app_store_connect/client'
9
+ require 'app_store_connect/schema'
10
+ require 'app_store_connect/type'
11
+ require 'app_store_connect/version'
12
+
15
13
  require 'app_store_connect/bundle_id_create_request'
16
- require 'app_store_connect/device_create_request'
17
- require 'app_store_connect/profile_create_request'
18
14
  require 'app_store_connect/certificate_create_request'
15
+ require 'app_store_connect/device_create_request'
19
16
  require 'app_store_connect/user_invitation_create_request'
20
- require 'app_store_connect/version'
21
-
22
- require 'app_store_connect/type'
23
- require 'app_store_connect/type/enum'
24
-
25
- require 'app_store_connect/factory'
26
- require 'app_store_connect/factory/builder/enum'
17
+ require 'app_store_connect/profile_create_request'
27
18
 
28
19
  module AppStoreConnect
29
- Factory.register('enum', Factory::Builder::Enum)
30
-
31
20
  @config = {}
32
21
 
33
22
  SCHEMA = Schema.new(File.join(__dir__, './config/schema.json'))
34
- Parser.parse!(SCHEMA)
35
23
 
36
24
  class << self
37
- attr_reader :config
25
+ attr_accessor :config
38
26
 
39
- attr_writer :config
27
+ def load!
28
+ SCHEMA.types.each do |type_schema|
29
+ options = type_schema.options
30
+ klass = Factory.type(type_schema)
31
+ name = options[:type]
32
+
33
+ AppStoreConnect::Type.const_set(name, klass)
34
+ end
35
+ end
40
36
  end
37
+
38
+ load!
41
39
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'jwt'
4
+
3
5
  module AppStoreConnect
4
6
  class Authorization
5
7
  AUDIENCE = 'appstoreconnect-v1'
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'app_store_connect/create_request'
4
+
3
5
  module AppStoreConnect
4
6
  class BundleIdCreateRequest < CreateRequest
5
7
  data do
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'app_store_connect/create_request'
4
+
3
5
  module AppStoreConnect
4
6
  class CertificateCreateRequest < CreateRequest
5
7
  data do
@@ -2,8 +2,8 @@
2
2
 
3
3
  require 'active_support/all'
4
4
 
5
- require 'app_store_connect/web_service_endpoint'
6
5
  require 'app_store_connect/request'
6
+ require 'app_store_connect/authorization'
7
7
 
8
8
  module AppStoreConnect
9
9
  class Client
@@ -15,46 +15,37 @@ module AppStoreConnect
15
15
  key_id: @options[:key_id],
16
16
  issuer_id: @options[:issuer_id]
17
17
  )
18
- @web_service_endpoints_by_name ||= begin
19
- AppStoreConnect::SCHEMA.web_service_endpoints.map do |config|
20
- [config.fetch('alias').to_sym, WebServiceEndpoint.new(**config.deep_symbolize_keys)]
21
- end.to_h
22
- end
18
+ @web_service_endpoints_by_alias ||= AppStoreConnect::SCHEMA
19
+ .web_service_endpoints
20
+ .map { |s| [s.alias, s] }
21
+ .to_h
23
22
  end
24
23
 
25
24
  def respond_to_missing?(method_name, include_private = false)
26
- web_service_endpoint_names.include?(method_name) || super
25
+ web_service_endpoint_aliases.include?(method_name) || super
27
26
  end
28
27
 
29
28
  def method_missing(method_name, *kwargs)
30
- super unless web_service_endpoint_names.include?(method_name)
29
+ super unless web_service_endpoint_aliases.include?(method_name)
31
30
 
32
- web_service_endpoint = web_service_endpoint_by(name: method_name)
31
+ web_service_endpoint = web_service_endpoint_by(method_name)
33
32
 
34
33
  call(web_service_endpoint, *kwargs)
35
34
  end
36
35
 
37
36
  private
38
37
 
39
- def web_service_endpoint_names
40
- @web_service_endpoints_by_name.keys
38
+ def web_service_endpoint_aliases
39
+ @web_service_endpoints_by_alias.keys
41
40
  end
42
41
 
43
42
  def call(web_service_endpoint, **kwargs)
44
- parser = proc do |response|
45
- JSON.parse(response.body) if response.body
46
- end
43
+ raise "invalid http method: #{web_service_endpoint.http_method}" unless %i[get delete post].include?(web_service_endpoint.http_method)
47
44
 
48
- case web_service_endpoint.http_method
49
- when :get
50
- get(web_service_endpoint, **kwargs, &parser)
51
- when :post
52
- post(web_service_endpoint, **kwargs, &parser)
53
- when :delete
54
- delete(web_service_endpoint, **kwargs, &parser)
55
- else
56
- raise "invalid http method: #{web_service_endpoint.http_method}"
57
- end
45
+ request = build_request(web_service_endpoint, **kwargs)
46
+ response = request.execute
47
+
48
+ JSON.parse(response.body) if response.body
58
49
  end
59
50
 
60
51
  def build_uri(web_service_endpoint, **kwargs)
@@ -63,8 +54,8 @@ module AppStoreConnect
63
54
  .gsub(/(\{(\w+)\})/) { kwargs.fetch(Regexp.last_match(2).to_sym) })
64
55
  end
65
56
 
66
- def web_service_endpoint_by(name:)
67
- @web_service_endpoints_by_name[name]
57
+ def web_service_endpoint_by(alias_sym)
58
+ @web_service_endpoints_by_alias[alias_sym]
68
59
  end
69
60
 
70
61
  def env_options
@@ -87,18 +78,6 @@ module AppStoreConnect
87
78
  end
88
79
  end
89
80
 
90
- def get(web_service_endpoint, **kwargs, &block)
91
- request = Request.new(
92
- kwargs: kwargs,
93
- web_service_endpoint: web_service_endpoint,
94
- http_method: :get,
95
- uri: build_uri(web_service_endpoint, **kwargs),
96
- headers: headers
97
- )
98
-
99
- request.execute(&block)
100
- end
101
-
102
81
  def http_body(web_service_endpoint, **kwargs)
103
82
  "AppStoreConnect::#{web_service_endpoint.http_body_type}"
104
83
  .constantize
@@ -108,29 +87,18 @@ module AppStoreConnect
108
87
  .to_json
109
88
  end
110
89
 
111
- def delete(web_service_endpoint, **kwargs, &block)
112
- request = Request.new(
113
- web_service_endpoint: web_service_endpoint,
90
+ def build_request(web_service_endpoint, **kwargs)
91
+ options = {
114
92
  kwargs: kwargs,
115
- http_method: :delete,
93
+ web_service_endpoint: web_service_endpoint,
94
+ http_method: web_service_endpoint.http_method,
116
95
  uri: build_uri(web_service_endpoint, **kwargs),
117
96
  headers: headers
118
- )
119
-
120
- request.execute(&block) || true
121
- end
97
+ }
122
98
 
123
- def post(web_service_endpoint, **kwargs, &block)
124
- request = Request.new(
125
- web_service_endpoint: web_service_endpoint,
126
- kwargs: kwargs,
127
- http_method: :post,
128
- uri: build_uri(web_service_endpoint, **kwargs),
129
- headers: headers,
130
- http_body: http_body(web_service_endpoint, **kwargs)
131
- )
99
+ options[:http_body] = http_body(web_service_endpoint, **kwargs) if web_service_endpoint.http_method == :post
132
100
 
133
- request.execute(&block)
101
+ Request.new(options)
134
102
  end
135
103
 
136
104
  def headers
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'app_store_connect/create_request'
4
+
3
5
  module AppStoreConnect
4
6
  class DeviceCreateRequest < CreateRequest
5
7
  data do
@@ -2,24 +2,10 @@
2
2
 
3
3
  module AppStoreConnect
4
4
  class Factory
5
- class BuilderNotRegistered < StandardError
6
- def initialize(name)
7
- super("Builder not registered: #{name}")
5
+ def self.type(schema)
6
+ Class.new(Type::Enum) do |base|
7
+ base.const_set('VALUES', schema.values)
8
8
  end
9
9
  end
10
-
11
- def self.register(name, builder)
12
- builders[name] = builder
13
- end
14
-
15
- def self.builders
16
- @builders ||= {}
17
- end
18
-
19
- def self.build(name, options = {})
20
- builders.fetch(name) do
21
- raise BuilderNotRegistered, name
22
- end.call(options)
23
- end
24
10
  end
25
11
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'app_store_connect/create_request'
4
+
3
5
  module AppStoreConnect
4
6
  class ProfileCreateRequest < CreateRequest
5
7
  data do
@@ -19,9 +19,7 @@ module AppStoreConnect
19
19
 
20
20
  def execute
21
21
  Net::HTTP.start(uri.host, uri.port, net_http_options) do |http|
22
- response = http.request(request)
23
-
24
- yield response if block_given?
22
+ http.request(request)
25
23
  end
26
24
  end
27
25
 
@@ -34,11 +32,12 @@ module AppStoreConnect
34
32
  def query
35
33
  return unless http_method == :get
36
34
 
37
- kwargs.dup.tap do |hash|
38
- url_parameter_names(web_service_endpoint).each do |name|
39
- hash.delete(name.to_sym)
40
- end
41
- end.to_query
35
+ names = url_parameter_names(web_service_endpoint)
36
+
37
+ kwargs
38
+ .reject { |n| names.include?(n) }
39
+ .deep_transform_keys { |k| k.to_s.camelize(:lower) }
40
+ .to_query
42
41
  end
43
42
 
44
43
  def http_method
@@ -1,17 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'app_store_connect/schema/type'
4
+ require 'app_store_connect/schema/web_service_endpoint'
5
+
3
6
  module AppStoreConnect
4
7
  class Schema
5
- def initialize(path)
6
- @schema = JSON.parse(File.read(path))
7
- end
8
+ attr_reader :types, :web_service_endpoints
8
9
 
9
- def types
10
- @schema['Type']
11
- end
12
-
13
- def web_service_endpoints
14
- @schema['web_service_endpoints']
10
+ def initialize(path)
11
+ schema = JSON.parse(File.read(path)).deep_symbolize_keys
12
+ @types = schema[:types].map do |options|
13
+ Type.new(**options)
14
+ end
15
+ @web_service_endpoints = schema[:web_service_endpoints].map do |s|
16
+ WebServiceEndpoint.new(**s)
17
+ end
15
18
  end
16
19
  end
17
20
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AppStoreConnect
4
+ class Schema
5
+ class Type
6
+ attr_reader :type, :options
7
+
8
+ def initialize(**options)
9
+ @type = options[:type]
10
+ @options = options
11
+ end
12
+
13
+ def values
14
+ @options[:values]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AppStoreConnect
4
+ class Schema
5
+ class WebServiceEndpoint
6
+ def initialize(**options)
7
+ @options = options
8
+ end
9
+
10
+ def alias
11
+ @options.fetch(:alias).to_sym
12
+ end
13
+
14
+ def http_method
15
+ @options[:http_method].to_sym
16
+ end
17
+
18
+ def http_body_type
19
+ @options[:http_body_type]
20
+ end
21
+
22
+ def url
23
+ @options[:url]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'app_store_connect/type/enum'
4
+
3
5
  module AppStoreConnect
4
6
  module Type
5
7
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppStoreConnect
4
- VERSION = '0.10.0'
4
+ VERSION = '0.11.0'
5
5
  end
@@ -1,5 +1,10 @@
1
1
  {
2
2
  "web_service_endpoints": [
3
+ {
4
+ "alias": "sales_reports",
5
+ "http_method": "get",
6
+ "url": "https://api.appstoreconnect.apple.com/v1/salesReports"
7
+ },
3
8
  {
4
9
  "alias": "create_certificate",
5
10
  "http_method": "post",
@@ -106,37 +111,37 @@
106
111
  "url": "https://api.appstoreconnect.apple.com/v1/userInvitations"
107
112
  }
108
113
  ],
109
- "Type": {
110
- "CapabilityType": {
111
- "type": "enum",
112
- "values": [
113
- "ICLOUD",
114
- "IN_APP_PURCHASE",
115
- "GAME_CENTER",
116
- "PUSH_NOTIFICATIONS",
117
- "WALLET",
118
- "INTER_APP_AUDIO",
119
- "MAPS",
120
- "ASSOCIATED_DOMAINS",
121
- "PERSONAL_VPN",
122
- "APP_GROUPS",
123
- "HEALTHKIT",
124
- "HOMEKIT",
125
- "WIRELESS_ACCESSORY_CONFIGURATION",
126
- "APPLE_PAY",
127
- "DATA_PROTECTION",
128
- "SIRIKIT",
129
- "NETWORK_EXTENSIONS",
130
- "MULTIPATH",
131
- "HOT_SPOT",
132
- "NFC_TAG_READING",
133
- "CLASSKIT",
134
- "AUTOFILL_CREDENTIAL_PROVIDER",
135
- "ACCESS_WIFI_INFORMATION"
136
- ]
137
- },
138
- "CertificateType": {
139
- "type": "enum",
114
+ "types": [
115
+ {
116
+ "type": "CapabilityType",
117
+ "values": [
118
+ "ICLOUD",
119
+ "IN_APP_PURCHASE",
120
+ "GAME_CENTER",
121
+ "PUSH_NOTIFICATIONS",
122
+ "WALLET",
123
+ "INTER_APP_AUDIO",
124
+ "MAPS",
125
+ "ASSOCIATED_DOMAINS",
126
+ "PERSONAL_VPN",
127
+ "APP_GROUPS",
128
+ "HEALTHKIT",
129
+ "HOMEKIT",
130
+ "WIRELESS_ACCESSORY_CONFIGURATION",
131
+ "APPLE_PAY",
132
+ "DATA_PROTECTION",
133
+ "SIRIKIT",
134
+ "NETWORK_EXTENSIONS",
135
+ "MULTIPATH",
136
+ "HOT_SPOT",
137
+ "NFC_TAG_READING",
138
+ "CLASSKIT",
139
+ "AUTOFILL_CREDENTIAL_PROVIDER",
140
+ "ACCESS_WIFI_INFORMATION"
141
+ ]
142
+ },
143
+ {
144
+ "type": "CertificateType",
140
145
  "values": [
141
146
  "OS_DEVELOPMENT",
142
147
  "IOS_DISTRIBUTION",
@@ -147,15 +152,15 @@
147
152
  "DEVELOPER_ID_APPLICATION"
148
153
  ]
149
154
  },
150
- "BundleIdPlatform": {
151
- "type": "enum",
155
+ {
156
+ "type": "BundleIdPlatform",
152
157
  "values": [
153
158
  "IOS",
154
159
  "MAC_OS"
155
160
  ]
156
161
  },
157
- "UserRole": {
158
- "type": "enum",
162
+ {
163
+ "type": "UserRole",
159
164
  "values": [
160
165
  "ADMIN",
161
166
  "FINANCE",
@@ -170,5 +175,5 @@
170
175
  "CUSTOMER_REPORTS"
171
176
  ]
172
177
  }
173
- }
178
+ ]
174
179
  }
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: app_store_connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Decot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-20 00:00:00.000000000 Z
11
+ date: 2019-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 5.2.3
19
+ version: 5.1.7
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 5.2.3
26
+ version: 5.1.7
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: jwt
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '2.1'
33
+ version: '1.4'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '2.1'
40
+ version: '1.4'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -210,20 +210,19 @@ files:
210
210
  - lib/app_store_connect/create_request.rb
211
211
  - lib/app_store_connect/device_create_request.rb
212
212
  - lib/app_store_connect/factory.rb
213
- - lib/app_store_connect/factory/builder/enum.rb
214
213
  - lib/app_store_connect/object/attributes.rb
215
214
  - lib/app_store_connect/object/data.rb
216
215
  - lib/app_store_connect/object/properties.rb
217
216
  - lib/app_store_connect/object/type.rb
218
- - lib/app_store_connect/parser.rb
219
217
  - lib/app_store_connect/profile_create_request.rb
220
218
  - lib/app_store_connect/request.rb
221
219
  - lib/app_store_connect/schema.rb
220
+ - lib/app_store_connect/schema/type.rb
221
+ - lib/app_store_connect/schema/web_service_endpoint.rb
222
222
  - lib/app_store_connect/type.rb
223
223
  - lib/app_store_connect/type/enum.rb
224
224
  - lib/app_store_connect/user_invitation_create_request.rb
225
225
  - lib/app_store_connect/version.rb
226
- - lib/app_store_connect/web_service_endpoint.rb
227
226
  - lib/config/schema.json
228
227
  homepage: https://github.com/kyledecot/app_store_connect
229
228
  licenses:
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AppStoreConnect
4
- class Factory
5
- module Builder
6
- class Enum
7
- def self.call(values:)
8
- Class.new(Type::Enum) do |base|
9
- base.const_set('VALUES', values)
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AppStoreConnect
4
- class Parser
5
- def self.parse!(schema)
6
- parse_types(schema.types)
7
- end
8
-
9
- def self.parse_types(types)
10
- types.each do |name, options|
11
- type = options.delete('type')
12
-
13
- klass = Factory.build(type, options.deep_symbolize_keys)
14
-
15
- AppStoreConnect::Type.const_set(name, klass)
16
- end
17
- end
18
- private_class_method :parse_types
19
- end
20
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AppStoreConnect
4
- class WebServiceEndpoint
5
- def initialize(**options)
6
- @options = options
7
- end
8
-
9
- def http_method
10
- @options[:http_method].to_sym
11
- end
12
-
13
- def http_body_type
14
- @options[:http_body_type]
15
- end
16
-
17
- def url
18
- @options[:url]
19
- end
20
- end
21
- end