globalid 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of globalid might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/lib/global_id/global_id.rb +2 -1
- data/lib/global_id/identification.rb +4 -4
- data/lib/global_id/locator.rb +46 -20
- data/lib/global_id/uri/gid.rb +17 -3
- metadata +14 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 14fc719e31ef97f014044c96e42be88e4b563a63
|
4
|
+
data.tar.gz: ab0206d64fb1aa095311f86e4be0636d447c28d7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fcfdb39821eb767d1b1f8d86b60813ab4c6a85f71956e294852f279252b7cb5952c5776cceaa23d578f7163ce7431e97fbc18b272254eb15a5cfd2679efc625d
|
7
|
+
data.tar.gz: 2d7ac23c3a6eaf8036d2f42b12299b037438be020316622318f69c9a0df580dc87511610c55b316ba3fd0848e9f479912654979939077fb9f5aa28c712467b0d
|
data/lib/global_id/global_id.rb
CHANGED
@@ -11,7 +11,8 @@ class GlobalID
|
|
11
11
|
|
12
12
|
def create(model, options = {})
|
13
13
|
if app = options.fetch(:app) { GlobalID.app }
|
14
|
-
|
14
|
+
params = options.except(:app, :verifier, :for)
|
15
|
+
new URI::GID.create(app, model, params), options
|
15
16
|
else
|
16
17
|
raise ArgumentError, 'An app is required to create a GlobalID. ' \
|
17
18
|
'Pass the :app option or set the default GlobalID.app.'
|
@@ -4,13 +4,13 @@ class GlobalID
|
|
4
4
|
module Identification
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
def to_global_id
|
8
|
-
@global_id ||= GlobalID.create(self)
|
7
|
+
def to_global_id(options = {})
|
8
|
+
@global_id ||= GlobalID.create(self, options)
|
9
9
|
end
|
10
10
|
alias to_gid to_global_id
|
11
11
|
|
12
|
-
def to_gid_param
|
13
|
-
to_global_id.to_param
|
12
|
+
def to_gid_param(options = {})
|
13
|
+
to_global_id(options).to_param
|
14
14
|
end
|
15
15
|
|
16
16
|
def to_signed_global_id(options = {})
|
data/lib/global_id/locator.rb
CHANGED
@@ -19,8 +19,11 @@ class GlobalID
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Takes an array of GlobalIDs or strings that can be turned into a GlobalIDs.
|
22
|
-
#
|
23
|
-
#
|
22
|
+
# All GlobalIDs must belong to the same app, as they will be located using
|
23
|
+
# the same locator using its locate_many method.
|
24
|
+
#
|
25
|
+
# By default the GlobalIDs will be located using Model.find(array_of_ids), so the
|
26
|
+
# models must respond to that finder signature.
|
24
27
|
#
|
25
28
|
# This approach will efficiently call only one #find (or #where(id: id), when using ignore_missing)
|
26
29
|
# per model class, but still interpolate the results to match the order in which the gids were passed.
|
@@ -37,13 +40,8 @@ class GlobalID
|
|
37
40
|
# we will use #where(id: ids) instead, which does not raise on missing records.
|
38
41
|
def locate_many(gids, options = {})
|
39
42
|
if (allowed_gids = parse_allowed(gids, options[:only])).any?
|
40
|
-
|
41
|
-
|
42
|
-
loaded_by_model = Hash[ids_by_model.map { |model, ids|
|
43
|
-
[ model, find_records(model, ids.map(&:last), ignore_missing: options[:ignore_missing]).index_by { |record| record.id.to_s } ]
|
44
|
-
}]
|
45
|
-
|
46
|
-
models_and_ids.collect { |(model, id)| loaded_by_model[model][id] }.compact
|
43
|
+
locator = locator_for(allowed_gids.first)
|
44
|
+
locator.locate_many(allowed_gids, options)
|
47
45
|
else
|
48
46
|
[]
|
49
47
|
end
|
@@ -108,7 +106,9 @@ class GlobalID
|
|
108
106
|
|
109
107
|
private
|
110
108
|
def locator_for(gid)
|
111
|
-
@locators.fetch(normalize_app(gid.app))
|
109
|
+
@locators.fetch(normalize_app(gid.app)) do
|
110
|
+
gid.model_class.respond_to?(:unscoped) ? UNSCOPED_LOCATOR : DEFAULT_LOCATOR
|
111
|
+
end
|
112
112
|
end
|
113
113
|
|
114
114
|
def find_allowed?(model_class, only = nil)
|
@@ -122,26 +122,48 @@ class GlobalID
|
|
122
122
|
def normalize_app(app)
|
123
123
|
app.to_s.downcase
|
124
124
|
end
|
125
|
-
|
126
|
-
def find_records(model_class, ids, options)
|
127
|
-
if options[:ignore_missing]
|
128
|
-
model_class.where(id: ids)
|
129
|
-
else
|
130
|
-
model_class.find(ids)
|
131
|
-
end
|
132
|
-
end
|
133
125
|
end
|
134
126
|
|
135
127
|
private
|
136
128
|
@locators = {}
|
137
129
|
|
138
|
-
class
|
130
|
+
class DefaultLocator
|
139
131
|
def locate(gid)
|
140
132
|
gid.model_class.find gid.model_id
|
141
133
|
end
|
134
|
+
|
135
|
+
def locate_many(gids, options = {})
|
136
|
+
models_and_ids = gids.collect { |gid| [ gid.model_class, gid.model_id ] }
|
137
|
+
ids_by_model = models_and_ids.group_by(&:first)
|
138
|
+
loaded_by_model = Hash[ids_by_model.map { |model, ids|
|
139
|
+
[ model, find_records(model, ids.map(&:last), ignore_missing: options[:ignore_missing]).index_by { |record| record.id.to_s } ]
|
140
|
+
}]
|
141
|
+
|
142
|
+
models_and_ids.collect { |(model, id)| loaded_by_model[model][id] }.compact
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
def find_records(model_class, ids, options)
|
147
|
+
if options[:ignore_missing]
|
148
|
+
model_class.where(id: ids)
|
149
|
+
else
|
150
|
+
model_class.find(ids)
|
151
|
+
end
|
152
|
+
end
|
142
153
|
end
|
154
|
+
DEFAULT_LOCATOR = DefaultLocator.new
|
143
155
|
|
144
|
-
|
156
|
+
class UnscopedLocator < DefaultLocator
|
157
|
+
def locate(gid)
|
158
|
+
gid.model_class.unscoped { super }
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
def find_records(model_class, ids, options)
|
163
|
+
model_class.unscoped { super }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
UNSCOPED_LOCATOR = UnscopedLocator.new
|
145
167
|
|
146
168
|
class BlockLocator
|
147
169
|
def initialize(block)
|
@@ -151,6 +173,10 @@ class GlobalID
|
|
151
173
|
def locate(gid)
|
152
174
|
@locator.call(gid)
|
153
175
|
end
|
176
|
+
|
177
|
+
def locate_many(gids, options = {})
|
178
|
+
gids.map { |gid| locate(gid) }
|
179
|
+
end
|
154
180
|
end
|
155
181
|
end
|
156
182
|
end
|
data/lib/global_id/uri/gid.rb
CHANGED
@@ -28,6 +28,9 @@ module URI
|
|
28
28
|
alias :app :host
|
29
29
|
attr_reader :model_name, :model_id, :params
|
30
30
|
|
31
|
+
# Raised when creating a Global ID for a model without an id
|
32
|
+
class MissingModelIdError < URI::InvalidComponentError; end
|
33
|
+
|
31
34
|
class << self
|
32
35
|
# Validates +app+'s as URI hostnames containing only alphanumeric characters
|
33
36
|
# and hyphens. An ArgumentError is raised if +app+ is invalid.
|
@@ -80,8 +83,11 @@ module URI
|
|
80
83
|
def build(args)
|
81
84
|
parts = Util.make_components_hash(self, args)
|
82
85
|
parts[:host] = parts[:app]
|
83
|
-
parts[:path] = "/#{parts[:model_name]}/#{parts[:model_id]}"
|
84
|
-
|
86
|
+
parts[:path] = "/#{parts[:model_name]}/#{CGI.escape(parts[:model_id].to_s)}"
|
87
|
+
|
88
|
+
if parts[:params] && !parts[:params].empty?
|
89
|
+
parts[:query] = URI.encode_www_form(parts[:params])
|
90
|
+
end
|
85
91
|
|
86
92
|
super parts
|
87
93
|
end
|
@@ -140,8 +146,9 @@ module URI
|
|
140
146
|
|
141
147
|
def set_model_components(path, validate = false)
|
142
148
|
_, model_name, model_id = path.match(PATH_REGEXP).to_a
|
149
|
+
model_id = CGI.unescape(model_id) if model_id
|
143
150
|
|
144
|
-
validate_component(model_name) &&
|
151
|
+
validate_component(model_name) && validate_model_id(model_id, model_name) if validate
|
145
152
|
|
146
153
|
@model_name = model_name
|
147
154
|
@model_id = model_id
|
@@ -154,6 +161,13 @@ module URI
|
|
154
161
|
"Expected a URI like gid://app/Person/1234: #{inspect}"
|
155
162
|
end
|
156
163
|
|
164
|
+
def validate_model_id(model_id, model_name)
|
165
|
+
return model_id unless model_id.blank?
|
166
|
+
|
167
|
+
raise MissingModelIdError, "Unable to create a Global ID for " \
|
168
|
+
"#{model_name} without a model id."
|
169
|
+
end
|
170
|
+
|
157
171
|
def parse_query_params(query)
|
158
172
|
Hash[URI.decode_www_form(query)].with_indifferent_access if query
|
159
173
|
end
|
metadata
CHANGED
@@ -1,46 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: globalid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.6
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- David Heinemeier Hansson
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2015-04
|
11
|
+
date: 2015-08-04 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activesupport
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 4.1.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 4.1.0
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
description: URIs for your models makes it easy to pass references around.
|
@@ -50,37 +45,37 @@ extensions: []
|
|
50
45
|
extra_rdoc_files: []
|
51
46
|
files:
|
52
47
|
- MIT-LICENSE
|
48
|
+
- lib/global_id.rb
|
53
49
|
- lib/global_id/global_id.rb
|
54
50
|
- lib/global_id/identification.rb
|
55
51
|
- lib/global_id/locator.rb
|
56
52
|
- lib/global_id/railtie.rb
|
57
53
|
- lib/global_id/signed_global_id.rb
|
58
54
|
- lib/global_id/uri/gid.rb
|
59
|
-
- lib/global_id.rb
|
60
55
|
- lib/globalid.rb
|
61
56
|
homepage: http://www.rubyonrails.org
|
62
57
|
licenses:
|
63
58
|
- MIT
|
59
|
+
metadata: {}
|
64
60
|
post_install_message:
|
65
61
|
rdoc_options: []
|
66
62
|
require_paths:
|
67
63
|
- lib
|
68
64
|
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
-
none: false
|
70
65
|
requirements:
|
71
|
-
- -
|
66
|
+
- - ">="
|
72
67
|
- !ruby/object:Gem::Version
|
73
68
|
version: 1.9.3
|
74
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
-
none: false
|
76
70
|
requirements:
|
77
|
-
- -
|
71
|
+
- - ">="
|
78
72
|
- !ruby/object:Gem::Version
|
79
73
|
version: '0'
|
80
74
|
requirements: []
|
81
75
|
rubyforge_project:
|
82
|
-
rubygems_version:
|
76
|
+
rubygems_version: 2.4.7
|
83
77
|
signing_key:
|
84
|
-
specification_version:
|
85
|
-
summary:
|
78
|
+
specification_version: 4
|
79
|
+
summary: 'Refer to any model with a URI: gid://app/class/id'
|
86
80
|
test_files: []
|
81
|
+
has_rdoc:
|