linked_rails 0.0.4.pre.g76dedd8ba → 0.0.4.pre.g83aa52ab3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c64c5a485e952fa401c1bcea4761f493b4f94650bbec75d7f19e9787dad1f84
4
- data.tar.gz: 4616e0044f6e3fefb204a464347c2dfc5d98adc0d12d11e8ef65e074968af3e0
3
+ metadata.gz: bc8a8c53b8422c4f81be3dbb64c8488b6d80a659b0fb585f252c6d66842f240c
4
+ data.tar.gz: 83172f0d901f0ad055186902ea9f9b5e9500b16bfa2071cad5533127765b57ec
5
5
  SHA512:
6
- metadata.gz: '08c5759176b7e96922b54ba4fdc60c42aa8513ea7265ac9e7e86e9b1f77726e4f113485896f891dc88f8ce056feebef844db3263dfc2d4327e43eb390e31f7f3'
7
- data.tar.gz: b915500d88b3a0cdb03d9e2d8e1d5f724967a353c138e0977afaef890162c423e0f57f2303db73b03004426042066cdeb24dfe6edc169efb104575bf3324c749
6
+ metadata.gz: 0c00be6915256007188a56ed84b1b485dd5c56fcf6e310ab525d66488f26498b0127abb4bf39f6e6b206192d0eed9410b891ba21407794653349bbcde95fc95b
7
+ data.tar.gz: d1488f86b20714eb98e4cbfdf9c8a6765e84be907dae2573274c02adc22047f0a6c206dc10ce2086823ab42028517d7f440e65b121aee53e35ba84b1e57f72b6
@@ -21,11 +21,8 @@ module LinkedRails
21
21
  return response_for_wrong_host(opts) if wrong_host?(opts[:iri])
22
22
 
23
23
  include = opts[:include].to_s == 'true'
24
- resource = LinkedRails.iri_mapper.resource_from_iri(request_path_to_url(opts[:iri]), user_context)
25
24
 
26
- return response_from_request(include, RDF::URI(opts[:iri])) if resource.blank?
27
-
28
- response_from_resource(include, opts[:iri], resource)
25
+ response_from_request(include, RDF::URI(opts[:iri]))
29
26
  rescue StandardError => e
30
27
  handle_resource_error(opts, e)
31
28
  end
@@ -87,13 +84,6 @@ module LinkedRails
87
84
  false
88
85
  end
89
86
 
90
- def resource_cache_control(cacheable, status, resource_policy)
91
- return :private unless status == 200 && cacheable
92
- return 'no-cache' unless resource_policy.try(:public_resource?)
93
-
94
- :public
95
- end
96
-
97
87
  def resource_params(param)
98
88
  params = param.permit(:include, :iri)
99
89
  params[:iri] = URI(params[:iri])
@@ -141,12 +131,6 @@ module LinkedRails
141
131
  }.merge(opts)
142
132
  end
143
133
 
144
- def resource_status(resource_policy)
145
- raise(LinkedRails::Errors::Forbidden.new(query: :show?)) unless resource_policy.show?
146
-
147
- 200
148
- end
149
-
150
134
  def response_for_wrong_host(opts)
151
135
  iri = opts[:iri]
152
136
  term = term_from_vocab(iri)
@@ -155,23 +139,6 @@ module LinkedRails
155
139
  ontology_term_response(iri, term, opts[:include])
156
140
  end
157
141
 
158
- def response_from_resource(include, iri, resource)
159
- resource_policy = policy(resource)
160
- status = resource_status(resource_policy)
161
-
162
- resource_response(
163
- iri,
164
- body: response_from_resource_body(include, iri, resource, status),
165
- cache: resource_cache_control(resource.try(:cacheable?), status, resource_policy),
166
- language: I18n.locale,
167
- status: status
168
- )
169
- end
170
-
171
- def response_from_resource_body(include, _iri, resource, status)
172
- include && status == 200 ? resource_body(resource) : nil
173
- end
174
-
175
142
  def term_from_vocab(iri)
176
143
  vocab = Vocab.for(iri)
177
144
  tag = iri.to_s.split(vocab.to_s).last
@@ -5,7 +5,6 @@ require 'pundit'
5
5
  module LinkedRails
6
6
  class Form # rubocop:disable Metrics/ClassLength
7
7
  include LinkedRails::Model
8
- include LinkedRails::Model::Cacheable
9
8
 
10
9
  class_attribute :abstract_form, :pages, :model_class
11
10
 
@@ -5,27 +5,6 @@ module LinkedRails
5
5
  include ActiveModel::Model
6
6
  include LinkedRails::Model
7
7
 
8
- def save
9
- Storage.hset(
10
- :persistent,
11
- :manifest,
12
- URL.as_href(LinkedRails.iri) => web_manifest.to_json
13
- )
14
- end
15
-
16
- def web_manifest
17
- web_manifest_base.merge(
18
- ontola: web_manifest_ontola_section,
19
- serviceworker: web_manifest_sw_section
20
- )
21
- end
22
-
23
- private
24
-
25
- def allowed_external_sources
26
- []
27
- end
28
-
29
8
  def app_name
30
9
  Rails.application.railtie_name.chomp('_application').humanize
31
10
  end
@@ -38,27 +17,8 @@ module LinkedRails
38
17
  '#eef0f2'
39
18
  end
40
19
 
41
- def blob_preview_iri
42
- return unless ActiveStorage::Blob.service.present?
43
-
44
- LinkedRails.iri(path: 'rails/active_storage/blobs/redirect/{signed_id}/preview')
45
- end
46
-
47
- def blob_upload_iri
48
- return unless ActiveStorage::Blob.service.present?
49
-
50
- LinkedRails.iri(path: 'rails/active_storage/direct_uploads')
51
- end
52
-
53
20
  def css_class; end
54
21
 
55
- def csp_entries
56
- {
57
- connectSrc: [ActiveStorage::Blob.service.try(:bucket)&.url].compact,
58
- scriptSrc: [ActiveStorage::Blob.service.try(:bucket)&.url].compact
59
- }
60
- end
61
-
62
22
  def header_background
63
23
  :primary
64
24
  end
@@ -67,16 +27,17 @@ module LinkedRails
67
27
  :white
68
28
  end
69
29
 
70
- def icons
71
- []
72
- end
73
-
74
- def lang
75
- :nl
30
+ def preload_iris
31
+ [
32
+ scope,
33
+ LinkedRails.iri(path: 'ns/core').to_s,
34
+ LinkedRails.iri(path: 'c_a').to_s,
35
+ LinkedRails.iri(path: 'menus').to_s
36
+ ]
76
37
  end
77
38
 
78
39
  def scope
79
- LinkedRails.iri.to_s
40
+ @scope ||= LinkedRails.iri.to_s
80
41
  end
81
42
 
82
43
  def site_theme_color
@@ -91,46 +52,43 @@ module LinkedRails
91
52
  app_name
92
53
  end
93
54
 
94
- def start_url
95
- scope == '/' ? scope : "#{scope}/"
96
- end
97
-
98
55
  def theme; end
99
56
 
100
57
  def theme_options
101
58
  {}
102
59
  end
103
60
 
61
+ def web_manifest
62
+ web_manifest_base.merge(
63
+ ontola: web_manifest_ontola_section,
64
+ serviceworker: web_manifest_sw_section
65
+ )
66
+ end
67
+
104
68
  def web_manifest_base # rubocop:disable Metrics/MethodLength
105
69
  {
106
70
  background_color: background_color,
107
71
  dir: :rtl,
108
72
  display: :standalone,
109
- icons: icons,
110
- lang: lang,
73
+ lang: :nl,
111
74
  name: app_name,
112
75
  scope: scope,
113
76
  short_name: app_name,
114
- start_url: start_url,
77
+ start_url: scope,
115
78
  theme_color: site_theme_color
116
79
  }
117
80
  end
118
81
 
119
82
  def web_manifest_ontola_section # rubocop:disable Metrics/MethodLength
120
83
  {
121
- allowed_external_sources: allowed_external_sources,
122
- blob_preview_iri: blob_preview_iri,
123
- blob_upload_iri: blob_upload_iri,
124
- csp: csp_entries,
84
+ css_class: css_class,
125
85
  header_background: header_background,
126
86
  header_text: header_text,
127
- preconnect: preconnect,
87
+ preload: preload_iris,
128
88
  primary_color: site_theme_color,
129
89
  secondary_color: site_secondary_color,
130
- styled_headers: styled_headers,
131
90
  theme: theme,
132
91
  theme_options: theme_options.to_query,
133
- tracking: tracking,
134
92
  website_iri: LinkedRails.iri.to_s,
135
93
  websocket_path: websocket_path
136
94
  }
@@ -138,7 +96,7 @@ module LinkedRails
138
96
 
139
97
  def web_manifest_sw_section
140
98
  {
141
- src: "#{scope.chomp('/')}/sw.js",
99
+ src: "#{scope}/sw.js?manifestLocation=#{Rack::Utils.escape("#{scope}/manifest.json")}",
142
100
  scope: scope
143
101
  }
144
102
  end
@@ -146,37 +104,5 @@ module LinkedRails
146
104
  def websocket_path
147
105
  Rails.application.config.try(:action_cable).try(:mount_path).try(:[], 1..-1)
148
106
  end
149
-
150
- def preconnect
151
- []
152
- end
153
-
154
- def styled_headers
155
- false
156
- end
157
-
158
- def tracking
159
- []
160
- end
161
-
162
- class << self
163
- def destroy(iri)
164
- Storage.hdel(:persistent, :manifest, URL.as_href(iri))
165
- end
166
-
167
- def move(from, to)
168
- Storage.hset(
169
- :persistent,
170
- :redirect_prefix,
171
- URL.as_href(from) => URL.as_href(to)
172
- )
173
-
174
- data = Storage.hget(:persistent, :manifest, URL.as_href(from))
175
-
176
- Storage.hset(:persistent, :manifest, URL.as_href(to), data) if data
177
-
178
- destroy(from)
179
- end
180
- end
181
107
  end
182
108
  end
@@ -26,7 +26,7 @@ module LinkedRails
26
26
  end
27
27
 
28
28
  def menus
29
- @menus ||= available_menus.map(&method(:memoized_menu_item))
29
+ @menus ||= available_menus.map(&method(:memoised_menu_item))
30
30
  end
31
31
 
32
32
  def menu(tag)
@@ -4,7 +4,6 @@ module LinkedRails
4
4
  class Ontology
5
5
  include ActiveModel::Model
6
6
  include LinkedRails::Model
7
- include LinkedRails::Model::Cacheable
8
7
 
9
8
  def classes
10
9
  @classes ||= LinkedRails.linked_models.map do |klass|
@@ -11,8 +11,6 @@ en:
11
11
  update:
12
12
  label: "Edit"
13
13
  success: 'Updated successfully'
14
- errors:
15
- access_denied: "You're not authorized for this action. (%{action})"
16
14
  linked_rails:
17
15
  status:
18
16
  400: "Error in request"
@@ -6,10 +6,6 @@ module LinkedRails
6
6
  extend ActiveSupport::Concern
7
7
  include ActiveSupport::Rescuable
8
8
 
9
- included do
10
- rescue_from LinkedRails::Errors::Forbidden, with: :handle_error
11
- end
12
-
13
9
  private
14
10
 
15
11
  def add_error_snackbar(error)
@@ -73,7 +69,6 @@ module LinkedRails
73
69
  'Doorkeeper::Errors::InvalidGrantReuse' => 422,
74
70
  'LinkedRails::Auth::Errors::Expired' => 410,
75
71
  'LinkedRails::Auth::Errors::Unauthorized' => 401,
76
- 'LinkedRails::Errors::Forbidden' => 403,
77
72
  'Pundit::NotAuthorizedError' => 403
78
73
  }
79
74
  end
@@ -46,13 +46,6 @@ module LinkedRails
46
46
 
47
47
  private
48
48
 
49
- def request_path_to_url(path)
50
- return path unless path.present? && URI(path).relative?
51
-
52
- port = [80, 443].include?(request.port) ? nil : request.port
53
- URI::Generic.new(request.scheme, nil, request.host, port, nil, path, nil, nil, nil).to_s
54
- end
55
-
56
49
  def build_new_resource
57
50
  controller_class.build_new(user_context: user_context)
58
51
  end
@@ -62,7 +62,6 @@ module LinkedRails
62
62
  iri = root_relative_iri.dup
63
63
  iri.scheme = LinkedRails.scheme
64
64
  iri.host = LinkedRails.host
65
- iri.path = iri.path.presence || '/'
66
65
  iri
67
66
  end
68
67
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'model/actionable'
4
- require_relative 'model/cacheable'
5
4
  require_relative 'model/collections'
6
5
  require_relative 'model/dirty'
7
6
  require_relative 'model/enhancements'
@@ -46,10 +46,6 @@ module LinkedRails
46
46
  self.class.policy_class
47
47
  end
48
48
 
49
- def public_resource?
50
- false
51
- end
52
-
53
49
  def show?
54
50
  false
55
51
  end
data/lib/linked_rails.rb CHANGED
@@ -22,10 +22,6 @@ module LinkedRails
22
22
 
23
23
  mattr_accessor :whitelisted_spi_ips
24
24
  mattr_writer :host, :scheme
25
- mattr_accessor :persistent_redis_database, default: ENV['PERSISTENT_REDIS_DATABASE'].presence || 6
26
- mattr_accessor :stream_redis_database, default: ENV['STREAM_REDIS_DATABASE'].presence || 7
27
- mattr_accessor :cache_redis_database, default: ENV['CACHE_REDIS_DATABASE'].presence || 8
28
- mattr_accessor :cache_stream, default: ENV['CACHE_STREAM'].presence || 'transactions'
29
25
 
30
26
  def self.configurable_class(parent, klass, default: nil, reader: nil) # rubocop:disable Metrics/AbcSize
31
27
  method = :"#{[parent, klass.to_s.downcase].compact.join('_')}_class"
@@ -54,10 +50,8 @@ module LinkedRails
54
50
  @@scheme ||= Rails.application.routes.default_url_options[:protocol] || :http # rubocop:disable Style/ClassVars
55
51
  end
56
52
 
57
- def iri(**args)
58
- opts = {scheme: LinkedRails.scheme, host: LinkedRails.host}.merge(args)
59
- opts[:path] = opts[:path].presence || '/'
60
- RDF::URI.new(**opts)
53
+ def iri(**opts)
54
+ RDF::URI.new(**{scheme: LinkedRails.scheme, host: LinkedRails.host}.merge(opts))
61
55
  end
62
56
  end
63
57
 
@@ -90,7 +84,6 @@ ActiveSupport::Inflector.inflections do |inflect|
90
84
  inflect.acronym 'SHACL'
91
85
  end
92
86
 
93
- require 'linked_rails/errors'
94
87
  require 'linked_rails/uri_template'
95
88
  require 'linked_rails/vocab'
96
89
  require 'linked_rails/cache'
@@ -108,5 +101,3 @@ require 'linked_rails/routes'
108
101
  require 'linked_rails/serializer'
109
102
  require 'linked_rails/translate'
110
103
  require 'linked_rails/railtie'
111
- require 'linked_rails/url'
112
- require 'linked_rails/storage'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linked_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4.pre.g76dedd8ba
4
+ version: 0.0.4.pre.g83aa52ab3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arthur Dingemans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-15 00:00:00.000000000 Z
11
+ date: 2022-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_response
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: redis
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: rdf
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -299,10 +285,8 @@ files:
299
285
  - app/policies/linked_rails/collection/view_policy.rb
300
286
  - app/policies/linked_rails/collection_policy.rb
301
287
  - app/policies/linked_rails/enum_value_policy.rb
302
- - app/policies/linked_rails/form_policy.rb
303
288
  - app/policies/linked_rails/menus/item_policy.rb
304
289
  - app/policies/linked_rails/menus/list_policy.rb
305
- - app/policies/linked_rails/ontology_policy.rb
306
290
  - app/policies/linked_rails/sequence_policy.rb
307
291
  - app/serializers/linked_rails/actions/item_serializer.rb
308
292
  - app/serializers/linked_rails/actions/object_serializer.rb
@@ -340,7 +324,6 @@ files:
340
324
  - app/serializers/linked_rails/web_page_serializer.rb
341
325
  - app/serializers/linked_rails/web_site_serializer.rb
342
326
  - app/serializers/linked_rails/widget_serializer.rb
343
- - app/workers/linked_rails/invalidation_stream_worker.rb
344
327
  - config/initializers/inflections.rb
345
328
  - lib/generators/linked_rails/install/install_generator.rb
346
329
  - lib/generators/linked_rails/install/templates/README
@@ -390,8 +373,6 @@ files:
390
373
  - lib/linked_rails/enhancements/destroyable/controller.rb
391
374
  - lib/linked_rails/enhancements/updatable/controller.rb
392
375
  - lib/linked_rails/enhancements/updatable/serializer.rb
393
- - lib/linked_rails/errors.rb
394
- - lib/linked_rails/errors/forbidden.rb
395
376
  - lib/linked_rails/helpers/delta_helper.rb
396
377
  - lib/linked_rails/helpers/ontola_actions_helper.rb
397
378
  - lib/linked_rails/helpers/resource_helper.rb
@@ -400,7 +381,6 @@ files:
400
381
  - lib/linked_rails/middleware/linked_data_params.rb
401
382
  - lib/linked_rails/model.rb
402
383
  - lib/linked_rails/model/actionable.rb
403
- - lib/linked_rails/model/cacheable.rb
404
384
  - lib/linked_rails/model/collections.rb
405
385
  - lib/linked_rails/model/dirty.rb
406
386
  - lib/linked_rails/model/enhancements.rb
@@ -424,12 +404,10 @@ files:
424
404
  - lib/linked_rails/serializer/actionable.rb
425
405
  - lib/linked_rails/serializer/menuable.rb
426
406
  - lib/linked_rails/serializer/singularable.rb
427
- - lib/linked_rails/storage.rb
428
407
  - lib/linked_rails/test_methods.rb
429
408
  - lib/linked_rails/translate.rb
430
409
  - lib/linked_rails/types/iri_type.rb
431
410
  - lib/linked_rails/uri_template.rb
432
- - lib/linked_rails/url.rb
433
411
  - lib/linked_rails/version.rb
434
412
  - lib/linked_rails/vocab.rb
435
413
  - lib/nill_class_renderer.rb
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module LinkedRails
4
- class FormPolicy < LinkedRails.policy_parent_class
5
- def show?
6
- true
7
- end
8
-
9
- def public_resource?
10
- true
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module LinkedRails
4
- class OntologyPolicy < LinkedRails.policy_parent_class
5
- def show?
6
- true
7
- end
8
-
9
- def public_resource?
10
- true
11
- end
12
- end
13
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module LinkedRails
4
- class InvalidationStreamWorker < ActiveJob::Base
5
- def perform(type, iri, resource_type)
6
- entry = {
7
- type: type,
8
- resource: iri,
9
- resourceType: resource_type
10
- }
11
- id = Storage.xadd(:stream, LinkedRails.cache_stream, entry)
12
-
13
- raise('No message id returned, implies failure') if id.blank?
14
- end
15
- end
16
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module LinkedRails
4
- module Errors
5
- class Forbidden < StandardError
6
- attr_reader :query, :record, :policy, :action
7
-
8
- # @param [Hash] options
9
- # @option options [String] query The action of the request
10
- # @option options [ActiveRecord::Base] record The record that was requested
11
- # @option options [Policy] policy The policy that raised the exception
12
- # @option options [String] message Override the default error message
13
- # @return [String] the message
14
- def initialize(**options)
15
- @query = options.fetch(:query).to_s
16
- @record = options[:record]
17
- @policy = options[:policy]
18
- @action = @query[-1] == '?' ? @query[0..-2] : @query
19
- @message = options[:message]
20
-
21
- raise StandardError if @query.blank? && @message.blank?
22
-
23
- super(@message || default_message)
24
- end
25
-
26
- private
27
-
28
- def default_message
29
- I18n.t(
30
- "pundit.#{@policy.class.to_s.underscore}.#{@query}",
31
- action: @action,
32
- default: I18n.t('errors.access_denied')
33
- )
34
- end
35
- end
36
- end
37
- end
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'errors/forbidden'
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module LinkedRails
4
- module Model
5
- module Cacheable
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- if respond_to?(:after_commit)
10
- after_commit :publish_create, on: :create, if: :should_publish_changes
11
- after_commit :publish_update, on: :update, if: :should_publish_changes
12
- after_commit :publish_delete, on: :destroy, if: :should_publish_changes
13
- end
14
- end
15
-
16
- def cacheable?
17
- true
18
- end
19
-
20
- def publish_create
21
- publish_message('io.ontola.transactions.Created')
22
- end
23
-
24
- def publish_update
25
- publish_message('io.ontola.transactions.Updated')
26
- end
27
-
28
- def publish_delete
29
- publish_message('io.ontola.transactions.Deleted')
30
- end
31
-
32
- private
33
-
34
- def publish_message(type)
35
- LinkedRails::InvalidationStreamWorker.perform_now(type, iri.to_s, self.class.iri.to_s)
36
- rescue StandardError
37
- LinkedRails::InvalidationStreamWorker.perform_later(type, iri.to_s, self.class.iri.to_s)
38
- end
39
-
40
- def should_publish_changes
41
- cacheable? && !Rails.env.test?
42
- end
43
- end
44
- end
45
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'redis'
4
-
5
- module LinkedRails
6
- class Storage
7
- REDIS_DB = {
8
- cache: LinkedRails.cache_redis_database,
9
- persistent: LinkedRails.persistent_redis_database,
10
- stream: LinkedRails.stream_redis_database
11
- }.freeze
12
- KEYS = {
13
- manifest: 'cache:Manifest',
14
- redirect_exact: 'cache:Redirect:Exact',
15
- redirect_prefix: 'cache:Redirect:Prefix'
16
- }.freeze
17
-
18
- class << self
19
- %i[xadd].each do |method|
20
- define_method(method) do |db, *args|
21
- Redis.new(db: REDIS_DB.fetch(db)).send(method, *args)
22
- end
23
- end
24
-
25
- %i[hset hdel hget].each do |method|
26
- define_method(method) do |db, key, *args|
27
- Redis.new(db: REDIS_DB.fetch(db)).send(method, KEYS.fetch(key), *args)
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,11 +0,0 @@
1
- module LinkedRails
2
- class URL
3
- class << self
4
- def as_href(url)
5
- uri = URI(url)
6
- uri.path = uri.path.presence || '/'
7
- uri.to_s
8
- end
9
- end
10
- end
11
- end