class URI::GID
def build(args)
Using an array, the arguments must be in order [app, model_name, model_id, params]:
URI::GID.build(app: 'bcx', model_name: 'Person', model_id: '1', params: { key: 'value' })
Using a hash:
either a hash or an array.
The allowed components are app, model_name, model_id and params, which can be
Create a new URI::GID from components with argument check.
def build(args) parts = Util.make_components_hash(self, args) parts[:host] = parts[:app] model_id_segment = Array(parts[:model_id]).map { |p| CGI.escape(p.to_s) }.join(COMPOSITE_MODEL_ID_DELIMITER) parts[:path] = "/#{parts[:model_name]}/#{model_id_segment}" if parts[:params] && !parts[:params].empty? parts[:query] = URI.encode_www_form(parts[:params]) end super parts end
def check_host(host)
def check_host(host) validate_component(host) super end
def check_path(path)
def check_path(path) validate_component(path) set_model_components(path, true) end
def check_scheme(scheme)
def check_scheme(scheme) if scheme == 'gid' true else raise URI::BadURIError, "Not a gid:// URI scheme: #{inspect}" end end
def create(app, model, params = nil)
Shorthand to build a URI::GID from an app, a model and optional params.
def create(app, model, params = nil) build app: app, model_name: model.class.name, model_id: model.id, params: params end
def deconstruct_keys(_keys)
def deconstruct_keys(_keys) {app: app, model_name: model_name, model_id: model_id, params: params} end
def parse(uri)
URI.parse('gid://bcx') # => URI::GID instance
URI('gid://bcx') # => URI::GID instance
This differs from URI() and URI.parse which do not check arguments.
URI::GID.parse 'gid://bcx/Person/1?key=value'
Create a new URI::GID by parsing a gid string with argument check.
def parse(uri) generic_components = URI.split(uri) << nil << true # nil parser, true arg_check new(*generic_components) end
def parse_query_params(query)
def parse_query_params(query) Hash[URI.decode_www_form(query)].with_indifferent_access if query end
def query=(query)
def query=(query) set_params parse_query_params(query) super end
def set_model_components(path, validate = false)
def set_model_components(path, validate = false) _, model_name, model_id = path.split('/', 3) validate_component(model_name) && validate_model_id_section(model_id, model_name) if validate @model_name = model_name if model_id model_id_parts = model_id .split(COMPOSITE_MODEL_ID_DELIMITER, COMPOSITE_MODEL_ID_MAX_SIZE) .reject(&:blank?) model_id_parts.map! do |id| validate_model_id(id) CGI.unescape(id) end @model_id = model_id_parts.length == 1 ? model_id_parts.first : model_id_parts end end
def set_params(params)
def set_params(params) @params = params end
def set_path(path)
def set_path(path) set_model_components(path) unless defined?(@model_name) && @model_id super end
def set_query(query)
def set_query(query) set_params parse_query_params(query) super end
def to_s
def to_s # Implement #to_s to avoid no implicit conversion of nil into string when path is nil "gid://#{app}#{path}#{'?' + query if query}" end
def validate_app(app)
URI::GID.validate_app(nil) # => ArgumentError
URI::GID.validate_app('foo-bar') # => 'foo-bar'
URI::GID.validate_app('bcx') # => 'bcx'
and hyphens. An ArgumentError is raised if +app+ is invalid.
Validates +app+'s as URI hostnames containing only alphanumeric characters
def validate_app(app) parse("gid://#{app}/Model/1").app rescue URI::Error raise ArgumentError, 'Invalid app name. ' \ 'App names must be valid URI hostnames: alphanumeric and hyphen characters only.' end
def validate_component(component)
def validate_component(component) return component unless component.blank? raise URI::InvalidComponentError, "Expected a URI like gid://app/Person/1234: #{inspect}" end
def validate_model_id(model_id_part)
def validate_model_id(model_id_part) return unless model_id_part.include?('/') raise InvalidModelIdError, "Unable to create a Global ID for " \ "#{model_name} with a malformed model id." end
def validate_model_id_section(model_id, model_name)
def validate_model_id_section(model_id, model_name) return model_id unless model_id.blank? raise MissingModelIdError, "Unable to create a Global ID for " \ "#{model_name} without a model id." end