Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rails/globalid
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.4.1
Choose a base ref
...
head repository: rails/globalid
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.0.1
Choose a head ref

Commits on Nov 2, 2017

  1. Improved documentation clarity around expiration

    - Moved the expiration document to the top since I think it's more important than "labels"
    - Broke up the large code block and reordered it to lead the reader along the sequence: signed global ids > which can expire > which expire by default in Rails > which aren't idempotent > how to get permanent SGIDs > how to expire at a specific time.
    ideasasylum authored Nov 2, 2017

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c67e586 View commit details

Commits on Nov 12, 2017

  1. Merge pull request #106 from ideasasylum/ideasasylum-improved-expirat…

    …ion-readme
    
    Improved documentation clarity around expiration
    kaspth authored Nov 12, 2017

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    695e02c View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    kaspth Kasper Timm Hansen
    Copy the full SHA
    3537675 View commit details
  3. Verified

    This commit was signed with the committer’s verified signature.
    kaspth Kasper Timm Hansen
    Copy the full SHA
    5bfe23a View commit details

Commits on Aug 15, 2018

  1. Array#uniq to correctly identify == GlobalIDs

    Ben Miller committed Aug 15, 2018
    Copy the full SHA
    05fac3e View commit details

Commits on Aug 17, 2018

  1. Ignore .lock files for tests

    Since we're not checking them in
    amatsuda committed Aug 17, 2018

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    f188c68 View commit details
  2. Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    e661f6c View commit details

Commits on Aug 22, 2018

  1. GlobalID::Identification clears memoized to_global_id on dup

    This module is used in ActiveRecord, which resets the model's primary key on
    `dup`. If we don't clear it here, then a `dup`ed ActiveRecord instance can have
    an invalid GlobalID.
    bradleybuda committed Aug 22, 2018

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    b9f78c0 View commit details

Commits on Aug 23, 2018

  1. Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    8b3af4c View commit details

Commits on Aug 24, 2018

  1. Merge pull request #109 from bradleybuda/master

    GlobalID::Identification clears memoized to_global_id on dup
    rafaelfranca authored Aug 24, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a9c4e1e View commit details

Commits on Aug 27, 2018

  1. Merge pull request #108 from fattymiller/uniq-equality

    Array#uniq to correctly identify == GlobalIDs
    rafaelfranca authored Aug 27, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    288ac24 View commit details

Commits on Oct 15, 2018

  1. Fix typo

    mgrachev authored and jeremy committed Oct 15, 2018
    Copy the full SHA
    d2a0ece View commit details

Commits on Oct 31, 2018

  1. Allow configuration in initializers

    Closes #105
    
    This sets `GlobalID.app` and `SecureGlobalID.expires_in` to the default
    values and then allows overwriting them via `config.global_id.app` and
    `config.global_id.expires_in` in an `config/initializers/*.rb`
    file.
    Joel Ambass authored and jeremy committed Oct 31, 2018
    Copy the full SHA
    3c8f909 View commit details

Commits on Dec 6, 2018

  1. Test against Rails 5.2

    y-yagi committed Dec 6, 2018
    Copy the full SHA
    16f47ac View commit details
  2. Copy the full SHA
    e3cf5cd View commit details
  3. Specify Rails env in a test of secret_key_base is not present

    In Rails 5.2, `secret_key_base` is generated automatically in
    environments of development and test.
    y-yagi committed Dec 6, 2018
    Copy the full SHA
    b4139ef View commit details
  4. Merge pull request #113 from y-yagi/test_against_rails_52

    Test against Rails 5.2
    y-yagi authored Dec 6, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6fae2d6 View commit details

Commits on Dec 11, 2018

  1. Test against latest Rubies

    y-yagi committed Dec 11, 2018
    Copy the full SHA
    c76b027 View commit details

Commits on Jan 11, 2019

  1. Release 0.4.2

    kaspth committed Jan 11, 2019
    Copy the full SHA
    ae7d97b View commit details
  2. Copy the full SHA
    c98b809 View commit details
  3. Verified

    This commit was signed with the committer’s verified signature.
    kaspth Kasper Timm Hansen
    Copy the full SHA
    e47bee1 View commit details
  4. Verified

    This commit was signed with the committer’s verified signature.
    kaspth Kasper Timm Hansen
    Copy the full SHA
    e5ee5e4 View commit details
  5. Verified

    This commit was signed with the committer’s verified signature.
    kaspth Kasper Timm Hansen
    Copy the full SHA
    25d1dd3 View commit details

Commits on Mar 24, 2019

  1. Explicitly specify secret_key_base in railtie test

    The railtie test fails at app startup because it does not have the tmp
    dir. This adds the secret_key_base so we don't need to generate one.
    
    Fixes #116.
    y-yagi committed Mar 24, 2019
    Copy the full SHA
    f80464d View commit details

Commits on Nov 6, 2019

  1. Bump loofah from 2.2.3 to 2.3.1

    Bumps [loofah](https://github.com/flavorjones/loofah) from 2.2.3 to 2.3.1.
    - [Release notes](https://github.com/flavorjones/loofah/releases)
    - [Changelog](https://github.com/flavorjones/loofah/blob/master/CHANGELOG.md)
    - [Commits](flavorjones/loofah@v2.2.3...v2.3.1)
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored Nov 6, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a067ed8 View commit details

Commits on Nov 13, 2019

  1. Merge pull request #118 from rails/dependabot/bundler/loofah-2.3.1

    Bump loofah from 2.2.3 to 2.3.1
    rafaelfranca authored Nov 13, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1d27840 View commit details

Commits on Nov 21, 2019

  1. Copy the full SHA
    dafd019 View commit details

Commits on Nov 28, 2019

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f4cf832 View commit details
  2. Merge pull request #120 from olleolleolle/patch-1

    Drop unused Travis sudo: false directive
    kaspth authored Nov 28, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1dc7f5e View commit details

Commits on Dec 15, 2019

  1. Merge pull request #119 from ideasasylum/docs/locate-many-description

    Add a description of locate_many / locate_many_signed
    kaspth authored Dec 15, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f10e45e View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    kaspth Kasper Timm Hansen
    Copy the full SHA
    f2bf0a0 View commit details

Commits on Dec 18, 2019

  1. Bump rack from 2.0.6 to 2.0.8

    Bumps [rack](https://github.com/rack/rack) from 2.0.6 to 2.0.8.
    - [Release notes](https://github.com/rack/rack/releases)
    - [Changelog](https://github.com/rack/rack/blob/master/CHANGELOG.md)
    - [Commits](rack/rack@2.0.6...2.0.8)
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored Dec 18, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ef5ee3b View commit details
  2. Merge pull request #121 from rails/dependabot/bundler/rack-2.0.8

    Bump rack from 2.0.6 to 2.0.8
    kaspth authored Dec 18, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bdcbc03 View commit details

Commits on Feb 28, 2020

  1. Bump rake from 12.3.2 to 12.3.3

    Bumps [rake](https://github.com/ruby/rake) from 12.3.2 to 12.3.3.
    - [Release notes](https://github.com/ruby/rake/releases)
    - [Changelog](https://github.com/ruby/rake/blob/master/History.rdoc)
    - [Commits](ruby/rake@v12.3.2...v12.3.3)
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored Feb 28, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6a90e4b View commit details

Commits on Mar 2, 2020

  1. Merge pull request #122 from rails/dependabot/bundler/rake-12.3.3

    Bump rake from 12.3.2 to 12.3.3
    rafaelfranca authored Mar 2, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e86a5d7 View commit details

Commits on Apr 26, 2020

  1. Require time core extension for 1.year

    Since 39ab83a this file uses `1.year`
    without requiring the Active Support core extension that defines it.
    eugeneius committed Apr 26, 2020
    Copy the full SHA
    1aec708 View commit details
  2. Merge pull request #123 from rails/require_core_ext_time

    Require time core extension for 1.year
    eugeneius authored Apr 26, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c54d0f2 View commit details
  3. Use 5-2-stable branch to fix Ruby 2.2 CI

    Rails 5.2.4.2 accidentally broke compatibility with Ruby 2.2 by using
    the safe navigation operator. It's been fixed on the 5-2-stable branch,
    but there may never be another 5.2 release, so to get CI passing we'll
    have to use the branch.
    eugeneius committed Apr 26, 2020
    Copy the full SHA
    7ec7204 View commit details

Commits on Apr 28, 2020

  1. Merge pull request #124 from rails/ruby_2_2_rails_5_2_fix_ci

    Use 5-2-stable branch to fix Ruby 2.2 CI
    eugeneius authored Apr 28, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4458f13 View commit details

Commits on Jun 24, 2020

  1. Bump rack from 2.0.8 to 2.1.4

    Bumps [rack](https://github.com/rack/rack) from 2.0.8 to 2.1.4.
    - [Release notes](https://github.com/rack/rack/releases)
    - [Changelog](https://github.com/rack/rack/blob/master/CHANGELOG.md)
    - [Commits](rack/rack@2.0.8...2.1.4)
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored Jun 24, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    eb33a16 View commit details

Commits on Jul 6, 2020

  1. Merge pull request #125 from rails/dependabot/bundler/rack-2.1.4

    Bump rack from 2.0.8 to 2.1.4
    rafaelfranca authored Jul 6, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0f68538 View commit details

Commits on Jul 31, 2020

  1. Allow expires_in to be configured to nil globally

    This makes it possible to turn off expiration globally.
    
    Closes #127.
    tekin committed Jul 31, 2020

    Verified

    This commit was signed with the committer’s verified signature.
    tekin Tekin Süleyman
    Copy the full SHA
    433cae1 View commit details

Commits on Sep 12, 2020

  1. Merge pull request #128 from tekin/global-non-expiring-ids

    Allow expires_in to be configured to nil globally
    kaspth authored Sep 12, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6cdb13f View commit details

Commits on Nov 25, 2020

  1. Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    3f80296 View commit details
  2. Merge pull request #131 from amatsuda/rm_as_concern

    Remove reference to AS::Concern from GlobalID::Identification
    kaspth authored Nov 25, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8adb4ae View commit details

Commits on Jul 27, 2021

  1. Fix ruby-head support

    byroot committed Jul 27, 2021
    Copy the full SHA
    ea729ac View commit details
  2. Merge pull request #132 from casperisfine/ruby-head-support

    Fix ruby-head support
    byroot authored Jul 27, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9c11e48 View commit details
  3. Copy the full SHA
    b6ac3bc View commit details
  4. Copy the full SHA
    a359b20 View commit details
  5. Copy the full SHA
    3d8e64d View commit details
17 changes: 17 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.0, 2, 2.7, 2.6, 3-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 2.6-bullseye, 3-buster, 3.0-buster, 2-buster, 2.7-buster, 2.6-buster
ARG VARIANT=2-bullseye
FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-${VARIANT}

# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment this line to install additional gems.
# RUN gem install <your-gem-names-here>

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
43 changes: 43 additions & 0 deletions .devcontainer/base.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.0, 2, 2.7, 2.6, 3-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 2.6-bullseye, 3-buster, 3.0-buster, 2-buster, 2.7-buster, 2.6-buster
ARG VARIANT=2-bullseye
FROM ruby:${VARIANT}

# Copy library scripts to execute
COPY library-scripts/*.sh library-scripts/*.env /tmp/library-scripts/

# [Option] Install zsh
ARG INSTALL_ZSH="true"
# [Option] Upgrade OS packages to their latest versions
ARG UPGRADE_PACKAGES="true"
# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# Remove imagemagick due to https://security-tracker.debian.org/tracker/CVE-2019-10131
&& apt-get purge -y imagemagick imagemagick-6-common \
# Install common packages, non-root user, rvm, core build tools
&& bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" "true" "true" \
&& bash /tmp/library-scripts/ruby-debian.sh "none" "${USERNAME}" "true" "true" \
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*

# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
ARG NODE_VERSION="none"
ENV NVM_DIR=/usr/local/share/nvm
ENV NVM_SYMLINK_CURRENT=true \
PATH=${NVM_DIR}/current/bin:${PATH}
RUN bash /tmp/library-scripts/node-debian.sh "${NVM_DIR}" "${NODE_VERSION}" "${USERNAME}" \
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*

# Remove library scripts for final image
RUN rm -rf /tmp/library-scripts

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment this line to install additional gems.
# RUN gem install <your-gem-names-here>

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
37 changes: 37 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.205.2/containers/ruby
{
"name": "Ruby",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Update 'VARIANT' to pick a Ruby version: 3, 3.0, 2, 2.7, 2.6
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"VARIANT": "3-bullseye",
// Options
"NODE_VERSION": "lts/*"
}
},

// Set *default* container specific settings.json values on container create.
"settings": {},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"rebornix.Ruby"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "ruby --version",

// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"features": {
"github-cli": "latest"
}

}
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: CI
on: [push, pull_request]
jobs:
tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby: [ 2.5, 2.6, 2.7 ]
rails: [ '5.0', '5.1', '5.2', '6.0', '6.1' ]
include:
- ruby: '3.0'
rails: '6.0'
- ruby: '3.0'
rails: '6.1'
- ruby: head
rails: '6.0'
- ruby: head
rails: '6.1'
- ruby: truffleruby
rails: '6.0'
- ruby: truffleruby
rails: '6.1'

env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_${{ matrix.rails }}.gemfile

steps:
- uses: actions/checkout@v2

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true

- name: Run tests
run: bundle exec rake test
continue-on-error: ${{ matrix.ruby == 'head' || matrix.ruby == 'truffleruby' }}
timeout-minutes: 3
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/.ruby-version
/.ruby-gemset
gemfiles/*.gemfile.lock
pkg
45 changes: 0 additions & 45 deletions .travis.yml

This file was deleted.

87 changes: 45 additions & 42 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,65 +1,68 @@
PATH
remote: .
specs:
globalid (0.4.1)
activesupport (>= 4.2.0)
globalid (1.0.0)
activesupport (>= 5.0)

GEM
remote: https://rubygems.org/
specs:
actionpack (5.1.4)
actionview (= 5.1.4)
activesupport (= 5.1.4)
rack (~> 2.0)
actionpack (6.1.4.1)
actionview (= 6.1.4.1)
activesupport (= 6.1.4.1)
rack (~> 2.0, >= 2.0.9)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.1.4)
activesupport (= 5.1.4)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (6.1.4.1)
activesupport (= 6.1.4.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activemodel (5.1.4)
activesupport (= 5.1.4)
activesupport (5.1.4)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activemodel (6.1.4.1)
activesupport (= 6.1.4.1)
activesupport (6.1.4.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
builder (3.2.3)
concurrent-ruby (1.0.5)
crass (1.0.2)
erubi (1.7.0)
i18n (0.9.0)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
builder (3.2.4)
concurrent-ruby (1.1.9)
crass (1.0.6)
erubi (1.10.0)
i18n (1.8.11)
concurrent-ruby (~> 1.0)
loofah (2.1.1)
loofah (2.12.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
method_source (0.9.0)
mini_portile2 (2.3.0)
minitest (5.10.3)
nokogiri (1.8.1)
mini_portile2 (~> 2.3.0)
rack (2.0.3)
rack-test (0.7.0)
method_source (1.0.0)
mini_portile2 (2.6.1)
minitest (5.14.4)
nokogiri (1.12.5)
mini_portile2 (~> 2.6.1)
racc (~> 1.4)
racc (1.6.0)
rack (2.2.3)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
railties (5.1.4)
actionpack (= 5.1.4)
activesupport (= 5.1.4)
rails-html-sanitizer (1.4.2)
loofah (~> 2.3)
railties (6.1.4.1)
actionpack (= 6.1.4.1)
activesupport (= 6.1.4.1)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (12.1.0)
thor (0.20.0)
thread_safe (0.3.6)
tzinfo (1.2.3)
thread_safe (~> 0.1)
rake (>= 0.13)
thor (~> 1.0)
rake (13.0.6)
thor (1.1.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
zeitwerk (2.5.1)

PLATFORMS
ruby
@@ -71,4 +74,4 @@ DEPENDENCIES
rake

BUNDLED WITH
1.15.4
2.2.22
144 changes: 95 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
@@ -24,97 +24,143 @@ Mix `GlobalID::Identification` into any model with a `#find(id)` class method.
Support is automatically included in Active Record.

```ruby
>> person_gid = Person.find(1).to_global_id
=> #<GlobalID ...
person_gid = Person.find(1).to_global_id
# => #<GlobalID ...

>> person_gid.uri
=> #<URI ...
person_gid.uri
# => #<URI ...

>> person_gid.to_s
=> "gid://app/Person/1"
person_gid.to_s
# => "gid://app/Person/1"

>> GlobalID::Locator.locate person_gid
=> #<Person:0x007fae94bf6298 @id="1">
GlobalID::Locator.locate person_gid
# => #<Person:0x007fae94bf6298 @id="1">
```

### Signed Global IDs

For added security GlobalIDs can also be signed to ensure that the data hasn't been tampered with.

```ruby
>> person_sgid = Person.find(1).to_signed_global_id
=> #<SignedGlobalID:0x007fea1944b410>
person_sgid = Person.find(1).to_signed_global_id
# => #<SignedGlobalID:0x007fea1944b410>

>> person_sgid = Person.find(1).to_sgid
=> #<SignedGlobalID:0x007fea1944b410>
person_sgid = Person.find(1).to_sgid
# => #<SignedGlobalID:0x007fea1944b410>

>> person_sgid.to_s
=> "BAhJIh5naWQ6Ly9pZGluYWlkaS9Vc2VyLzM5NTk5BjoGRVQ=--81d7358dd5ee2ca33189bb404592df5e8d11420e"

>> GlobalID::Locator.locate_signed person_sgid
=> #<Person:0x007fae94bf6298 @id="1">
person_sgid.to_s
# => "BAhJIh5naWQ6Ly9pZGluYWlkaS9Vc2VyLzM5NTk5BjoGRVQ=--81d7358dd5ee2ca33189bb404592df5e8d11420e"

GlobalID::Locator.locate_signed person_sgid
# => #<Person:0x007fae94bf6298 @id="1">
```
You can even bump the security up some more by explaining what purpose a Signed Global ID is for.
In this way evildoers can't reuse a sign-up form's SGID on the login page. For example.

```ruby
>> signup_person_sgid = Person.find(1).to_sgid(for: 'signup_form')
=> #<SignedGlobalID:0x007fea1984b520

>> GlobalID::Locator.locate_signed(signup_person_sgid.to_s, for: 'signup_form')
=> #<Person:0x007fae94bf6298 @id="1">
```
**Expiration**

You can also have SGIDs that expire some time in the future. Useful if there's a resource,
Signed Global IDs can expire some time in the future. This is useful if there's a resource
people shouldn't have indefinite access to, like a share link.

```ruby
>> expiring_sgid = Document.find(5).to_sgid(expires_in: 2.hours, for: 'sharing')
=> #<SignedGlobalID:0x008fde45df8937 ...>
expiring_sgid = Document.find(5).to_sgid(expires_in: 2.hours, for: 'sharing')
# => #<SignedGlobalID:0x008fde45df8937 ...>

# Within 2 hours...
>> GlobalID::Locator.locate_signed(expiring_sgid.to_s, for: 'sharing')
=> #<Document:0x007fae94bf6298 @id="5">
GlobalID::Locator.locate_signed(expiring_sgid.to_s, for: 'sharing')
# => #<Document:0x007fae94bf6298 @id="5">

# More than 2 hours later...
>> GlobalID::Locator.locate_signed(expiring_sgid.to_s, for: 'sharing')
=> nil
GlobalID::Locator.locate_signed(expiring_sgid.to_s, for: 'sharing')
# => nil
```

>> explicit_expiring_sgid = SecretAgentMessage.find(5).to_sgid(expires_at: Time.now.advance(hours: 1))
=> #<SignedGlobalID:0x008fde45df8937 ...>
**In Rails, an auto-expiry of 1 month is set by default.** You can alter that deal
in an initializer with:

# 1 hour later...
>> GlobalID::Locator.locate_signed explicit_expiring_sgid.to_s
=> nil
```ruby
# config/initializers/global_id.rb
Rails.application.config.global_id.expires_in = 3.months
```

You can assign a default SGID lifetime like so:

```ruby
SignedGlobalID.expires_in = 1.month
```

This way any generated SGID will use that relative expiry.

It's worth noting that _expiring SGIDs are not idempotent_ because they encode the current timestamp; repeated calls to `to_sgid` will produce different results. For example, in Rails

```ruby
Document.find(5).to_sgid.to_s == Document.find(5).to_sgid.to_s
# => false
```

You need to explicitly pass `expires_in: nil` to generate a permanent SGID that will not expire,

```ruby
# Passing a false value to either expiry option turns off expiration entirely.
>> never_expiring_sgid = Document.find(5).to_sgid(expires_in: nil)
=> #<SignedGlobalID:0x008fde45df8937 ...>
never_expiring_sgid = Document.find(5).to_sgid(expires_in: nil)
# => #<SignedGlobalID:0x008fde45df8937 ...>

# Any time later...
>> GlobalID::Locator.locate_signed never_expiring_sgid
=> #<Document:0x007fae94bf6298 @id="5">
GlobalID::Locator.locate_signed never_expiring_sgid
# => #<Document:0x007fae94bf6298 @id="5">
```

It's also possible to pass a specific expiry time

```ruby
explicit_expiring_sgid = SecretAgentMessage.find(5).to_sgid(expires_at: Time.now.advance(hours: 1))
# => #<SignedGlobalID:0x008fde45df8937 ...>

# 1 hour later...
GlobalID::Locator.locate_signed explicit_expiring_sgid.to_s
# => nil
```
Note that an explicit `:expires_at` takes precedence over a relative `:expires_in`.

You can assign a default SGID lifetime like so:
**Purpose**

You can even bump the security up some more by explaining what purpose a Signed Global ID is for.
In this way evildoers can't reuse a sign-up form's SGID on the login page. For example.

```ruby
SignedGlobalID.expires_in = 1.month
signup_person_sgid = Person.find(1).to_sgid(for: 'signup_form')
# => #<SignedGlobalID:0x007fea1984b520

GlobalID::Locator.locate_signed(signup_person_sgid.to_s, for: 'signup_form')
# => #<Person:0x007fae94bf6298 @id="1">
```

This way any generated SGID will use that relative expiry.
### Locating many Global IDs

In Rails, an auto-expiry of 1 month is set by default. You can alter that deal
in an initializer with:
When needing to locate many Global IDs use `GlobalID::Locator.locate_many` or `GlobalID::Locator.locate_many_signed` for Signed Global IDs to allow loading
Global IDs more efficiently.

For instance, the default locator passes every `model_id` per `model_name` thus
using `model_name.where(id: model_ids)` versus `GlobalID::Locator.locate`'s `model_name.find(id)`.

In the case of looking up Global IDs from a database, it's only necessary to query
once per `model_name` as shown here:

```ruby
# config/initializers/global_id.rb
Rails.application.config.global_id.expires_in = 3.months
gids = users.concat(people).sort_by(&:id).map(&:to_global_id)
# => [#<GlobalID:0x00007ffd6a8411a0 @uri=#<URI::GID gid://app/User/1>>,
#<GlobalID:0x00007ffd675d32b8 @uri=#<URI::GID gid://app/Student/1>>,
#<GlobalID:0x00007ffd6a840b10 @uri=#<URI::GID gid://app/User/2>>,
#<GlobalID:0x00007ffd675d2c28 @uri=#<URI::GID gid://app/Student/2>>,
#<GlobalID:0x00007ffd6a840480 @uri=#<URI::GID gid://app/User/3>>,
#<GlobalID:0x00007ffd675d2598 @uri=#<URI::GID gid://app/Student/3>>]

GlobalID::Locator.locate_many gids
# SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3) [["id", 1], ["id", 2], ["id", 3]]
# SELECT "students".* FROM "students" WHERE "students"."id" IN ($1, $2, $3) [["id", 1], ["id", 2], ["id", 3]]
# => [#<User id: 1>, #<Student id: 1>, #<User id: 2>, #<Student id: 2>, #<User id: 3>, #<Student id: 3>]
```

Note the order is maintained in the returned results.

### Custom App Locator

A custom locator can be set for an app by calling `GlobalID::Locator.use` and providing an app locator to use for that app.
6 changes: 0 additions & 6 deletions gemfiles/rails_4.2.gemfile

This file was deleted.

1 change: 1 addition & 0 deletions gemfiles/rails_5.0.gemfile
Original file line number Diff line number Diff line change
@@ -2,5 +2,6 @@ source "https://rubygems.org"

gem "activemodel", "~> 5.0.0"
gem "railties", "~> 5.0.0"
gem "minitest", "~> 5.10.0"

gemspec path: "../"
6 changes: 6 additions & 0 deletions gemfiles/rails_5.2.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
source "https://rubygems.org"

gem "activemodel", "~> 5.2.0"
gem "railties", git: "https://github.com/rails/rails", branch: "5-2-stable"

gemspec path: "../"
6 changes: 6 additions & 0 deletions gemfiles/rails_6.0.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
source "https://rubygems.org"

gem "activemodel", "~> 6.0"
gem "railties", "~> 6.0"

gemspec path: "../"
6 changes: 6 additions & 0 deletions gemfiles/rails_6.1.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
source "https://rubygems.org"

gem "activemodel", "~> 6.1"
gem "railties", "~> 6.1"

gemspec path: "../"
6 changes: 3 additions & 3 deletions globalid.gemspec
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = 'globalid'
s.version = '0.4.1'
s.version = '1.0.1'
s.summary = 'Refer to any model with a URI: gid://app/class/id'
s.description = 'URIs for your models makes it easy to pass references around.'

s.required_ruby_version = '>= 1.9.3'
s.required_ruby_version = '>= 2.5.0'

s.license = 'MIT'

@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
s.files = Dir['MIT-LICENSE', 'README.md', 'lib/**/*']
s.require_path = 'lib'

s.add_runtime_dependency 'activesupport', '>= 4.2.0'
s.add_runtime_dependency 'activesupport', '>= 5.0'

s.add_development_dependency 'rake'
end
13 changes: 13 additions & 0 deletions lib/global_id/fixture_set.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

class GlobalID
module FixtureSet
def signed_global_id(fixture_set_name, label, column_type: :integer, **options)
identifier = identify(label, column_type)
model_name = default_fixture_model_name(fixture_set_name)
uri = URI::GID.build([GlobalID.app, model_name, identifier, {}])

SignedGlobalID.new(uri, **options)
end
end
end
5 changes: 5 additions & 0 deletions lib/global_id/global_id.rb
Original file line number Diff line number Diff line change
@@ -63,6 +63,11 @@ def model_class
def ==(other)
other.is_a?(GlobalID) && @uri == other.uri
end
alias_method :eql?, :==

def hash
self.class.hash | @uri.hash
end

def to_param
# remove the = padding character for a prettier param -- it'll be added back in parse_encoded_gid
6 changes: 1 addition & 5 deletions lib/global_id/identification.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
require 'active_support/concern'

class GlobalID
module Identification
extend ActiveSupport::Concern

def to_global_id(options = {})
@global_id ||= GlobalID.create(self, options)
GlobalID.create(self, options)
end
alias to_gid to_global_id

18 changes: 13 additions & 5 deletions lib/global_id/railtie.rb
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
require 'global_id'
require 'active_support'
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/integer/time'

class GlobalID
# = GlobalID Railtie
@@ -14,14 +15,16 @@ class Railtie < Rails::Railtie # :nodoc:
config.eager_load_namespaces << GlobalID

initializer 'global_id' do |app|
default_expires_in = 1.month
default_app_name = app.railtie_name.remove('_application').dasherize

app.config.global_id.app ||= app.railtie_name.remove('_application').dasherize
GlobalID.app = app.config.global_id.app

app.config.global_id.expires_in ||= 1.month
SignedGlobalID.expires_in = app.config.global_id.expires_in
GlobalID.app = app.config.global_id.app ||= default_app_name
SignedGlobalID.expires_in = app.config.global_id.fetch(:expires_in, default_expires_in)

config.after_initialize do
GlobalID.app = app.config.global_id.app ||= default_app_name
SignedGlobalID.expires_in = app.config.global_id.fetch(:expires_in, default_expires_in)

app.config.global_id.verifier ||= begin
GlobalID::Verifier.new(app.key_generator.generate_key('signed_global_ids'))
rescue ArgumentError
@@ -34,6 +37,11 @@ class Railtie < Rails::Railtie # :nodoc:
require 'global_id/identification'
send :include, GlobalID::Identification
end

ActiveSupport.on_load(:active_record_fixture_set) do
require 'global_id/fixture_set'
send :extend, GlobalID::FixtureSet
end
end
end
end
17 changes: 9 additions & 8 deletions lib/global_id/uri/gid.rb
Original file line number Diff line number Diff line change
@@ -123,9 +123,6 @@ def set_params(params)
private
COMPONENT = [ :scheme, :app, :model_name, :model_id, :params ].freeze

# Extracts model_name and model_id from the URI path.
PATH_REGEXP = %r(\A/([^/]+)/?([^/]+)?\z)

def check_host(host)
validate_component(host)
super
@@ -145,11 +142,11 @@ def check_scheme(scheme)
end

def set_model_components(path, validate = false)
_, model_name, model_id = path.match(PATH_REGEXP).to_a
model_id = CGI.unescape(model_id) if model_id

_, model_name, model_id = path.split('/', 3)
validate_component(model_name) && validate_model_id(model_id, model_name) if validate

model_id = CGI.unescape(model_id) if model_id

@model_name = model_name
@model_id = model_id
end
@@ -162,7 +159,7 @@ def validate_component(component)
end

def validate_model_id(model_id, model_name)
return model_id unless model_id.blank?
return model_id unless model_id.blank? || model_id.include?('/')

raise MissingModelIdError, "Unable to create a Global ID for " \
"#{model_name} without a model id."
@@ -173,5 +170,9 @@ def parse_query_params(query)
end
end

@@schemes['GID'] = GID
if respond_to?(:register_scheme)
register_scheme('GID', GID)
else
@@schemes['GID'] = GID
end
end
24 changes: 24 additions & 0 deletions test/cases/global_id_test.rb
Original file line number Diff line number Diff line change
@@ -190,6 +190,30 @@ class GlobalIDCreationTest < ActiveSupport::TestCase
person_gid = GlobalID.create(Person.new(5), app: nil)
end
end

test 'equality' do
p1 = Person.new(5)
p2 = Person.new(5)
p3 = Person.new(10)
assert_equal p1, p2
assert_not_equal p2, p3

gid1 = GlobalID.create(p1)
gid2 = GlobalID.create(p2)
gid3 = GlobalID.create(p3)
assert_equal gid1, gid2
assert_not_equal gid2, gid3

# hash and eql? to match for two GlobalID's pointing to the same object
assert_equal [gid1], [gid1, gid2].uniq
assert_equal [gid1, gid3], [gid1, gid2, gid3].uniq

# verify that the GlobalID's hash is different to the underlaying URI
assert_not_equal gid1.hash, gid1.uri.hash

# verify that URI and GlobalID do not pass the uniq test
assert_equal [gid1, gid1.uri], [gid1, gid1.uri].uniq
end
end

class GlobalIDCustomParamsTest < ActiveSupport::TestCase
8 changes: 8 additions & 0 deletions test/cases/global_identification_test.rb
Original file line number Diff line number Diff line change
@@ -29,4 +29,12 @@ class GlobalIdentificationTest < ActiveSupport::TestCase
assert_equal SignedGlobalID.create(@model, some: 'param'), @model.to_signed_global_id(some: 'param')
assert_equal SignedGlobalID.create(@model, some: 'param'), @model.to_sgid(some: 'param')
end

test 'dup should clear memoized to_global_id' do
global_id = @model.to_global_id
dup_model = @model.dup
dup_model.id = @model.id + 1
dup_global_id = dup_model.to_global_id
assert_not_equal global_id, dup_global_id
end
end
46 changes: 41 additions & 5 deletions test/cases/railtie_test.rb
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ def setup
@app = BlogApp::Application.new
@app.config.eager_load = false
@app.config.logger = Logger.new(nil)
@app.config.secret_key_base = ('x' * 30)
end

test 'GlobalID.app for Blog::Application defaults to blog' do
@@ -28,17 +29,52 @@ def setup
assert_equal 'foo', GlobalID.app
end

test 'SignedGlobalID.verifier defaults to Blog::Application.message_verifier(:signed_global_ids) when secret_token is present' do
@app.config.secret_token = ('x' * 30)
test 'SignedGlobalID.expires_in can be explicitly set to nil with config.global_id.expires_in' do
@app.config.global_id.expires_in = nil
@app.initialize!
assert_nil SignedGlobalID.expires_in
end

test 'config.global_id can be used to set configurations after the railtie has been loaded' do
@app.config.eager_load = true
@app.config.before_eager_load do
@app.config.global_id.app = 'foobar'
@app.config.global_id.expires_in = 1.year
end

@app.initialize!
assert_equal 'foobar', GlobalID.app
assert_equal 1.year, SignedGlobalID.expires_in
end

test 'config.global_id can be used to explicitly set SignedGlobalID.expires_in to nil after the railtie has been loaded' do
@app.config.eager_load = true
@app.config.before_eager_load do
@app.config.global_id.expires_in = nil
end

@app.initialize!
assert_nil SignedGlobalID.expires_in
end


test 'SignedGlobalID.verifier defaults to Blog::Application.message_verifier(:signed_global_ids) when secret_key_base is present' do
@app.initialize!
message = {id: 42}
signed_message = SignedGlobalID.verifier.generate(message)
assert_equal @app.message_verifier(:signed_global_ids).generate(message), signed_message
end

test 'SignedGlobalID.verifier defaults to nil when secret_token is not present' do
@app.initialize!
assert_nil SignedGlobalID.verifier
test 'SignedGlobalID.verifier defaults to nil when secret_key_base is not present' do
original_env, Rails.env = Rails.env, 'production'

begin
@app.config.secret_key_base = nil
@app.initialize!
assert_nil SignedGlobalID.verifier
ensure
Rails.env = original_env
end
end

test 'SignedGlobalID.verifier can be set with config.global_id.verifier =' do
1 change: 1 addition & 0 deletions test/helper.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'bundler/setup'
require 'forwardable'
require 'active_support'
require 'active_support/testing/autorun'