├── app ├── helpers │ └── .keep ├── jobs │ └── .keep ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── concerns │ │ └── .keep │ └── user.rb ├── views │ └── .keep ├── controllers │ ├── .keep │ └── concerns │ │ └── .keep └── assets │ ├── images │ └── sqids │ │ └── rails │ │ └── .keep │ ├── config │ └── sqids_rails_manifest.js │ └── stylesheets │ └── sqids │ └── rails │ └── .keep ├── test ├── controllers │ └── .keep ├── dummy │ ├── log │ │ └── .keep │ ├── lib │ │ └── assets │ │ │ └── .keep │ ├── app │ │ ├── assets │ │ │ ├── images │ │ │ │ └── .keep │ │ │ ├── config │ │ │ │ └── manifest.js │ │ │ └── stylesheets │ │ │ │ └── application.css │ │ ├── models │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ └── application_record.rb │ │ ├── views │ │ │ ├── layouts │ │ │ │ ├── mailer.text.erb │ │ │ │ ├── mailer.html.erb │ │ │ │ └── application.html.erb │ │ │ └── pwa │ │ │ │ ├── manifest.json.erb │ │ │ │ └── service-worker.js │ │ ├── helpers │ │ │ └── application_helper.rb │ │ ├── channels │ │ │ └── application_cable │ │ │ │ ├── channel.rb │ │ │ │ └── connection.rb │ │ ├── mailers │ │ │ └── application_mailer.rb │ │ ├── controllers │ │ │ └── application_controller.rb │ │ └── jobs │ │ │ └── application_job.rb │ ├── public │ │ ├── icon.png │ │ ├── icon.svg │ │ ├── 406-unsupported-browser.html │ │ ├── 500.html │ │ ├── 422.html │ │ └── 404.html │ ├── bin │ │ ├── rake │ │ ├── rails │ │ └── setup │ ├── config │ │ ├── environment.rb │ │ ├── cable.yml │ │ ├── boot.rb │ │ ├── initializers │ │ │ ├── sqids.rb │ │ │ ├── filter_parameter_logging.rb │ │ │ ├── permissions_policy.rb │ │ │ ├── assets.rb │ │ │ ├── inflections.rb │ │ │ └── content_security_policy.rb │ │ ├── routes.rb │ │ ├── locales │ │ │ └── en.yml │ │ ├── database.yml │ │ ├── application.rb │ │ ├── storage.yml │ │ ├── puma.rb │ │ └── environments │ │ │ ├── development.rb │ │ │ ├── test.rb │ │ │ └── production.rb │ ├── config.ru │ ├── Rakefile │ └── db │ │ ├── migrate │ │ └── 20240705145551_create_users.rb │ │ └── schema.rb ├── lib │ └── sqids │ │ ├── rails_test.rb │ │ └── rails │ │ └── model_test.rb └── test_helper.rb ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── lint.yml │ ├── tests.yml │ └── codeql.yml ├── lib ├── sqids-rails.rb ├── sqids │ ├── rails │ │ ├── version.rb │ │ ├── engine.rb │ │ └── model.rb │ └── rails.rb └── tasks │ └── sqids │ └── rails_tasks.rake ├── .standard.yml ├── Rakefile ├── .gitignore ├── Appraisals ├── Gemfile ├── gemfiles ├── rails_6_1.gemfile ├── rails_7_0.gemfile ├── rails_7_1.gemfile ├── rails_7_2.gemfile ├── rails_6_1.gemfile.lock ├── rails_7_0.gemfile.lock ├── rails_7_1.gemfile.lock └── rails_7_2.gemfile.lock ├── bin ├── rails ├── rake └── standardrb ├── CHANGELOG.md ├── sqids-rails.gemspec ├── LICENSE.txt ├── SECURITY.md ├── README.md ├── CODE_OF_CONDUCT.md └── Gemfile.lock /app/helpers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/jobs/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/views/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @tbhb -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/sqids/rails/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/config/sqids_rails_manifest.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/stylesheets/sqids/rails/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/sqids-rails.rb: -------------------------------------------------------------------------------- 1 | require "sqids/rails" 2 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /test/dummy/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /.standard.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | - standard-rails: 3 | target_rails_version: 7.1 4 | -------------------------------------------------------------------------------- /lib/sqids/rails/version.rb: -------------------------------------------------------------------------------- 1 | class Sqids 2 | module Rails 3 | VERSION = "0.2.0" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/dummy/public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbhb/sqids-rails/HEAD/test/dummy/public/icon.png -------------------------------------------------------------------------------- /test/dummy/app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../stylesheets .css 3 | -------------------------------------------------------------------------------- /test/lib/sqids/rails_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class Sqids::RailsTest < ActiveSupport::TestCase 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /lib/sqids/rails/engine.rb: -------------------------------------------------------------------------------- 1 | class Sqids 2 | module Rails 3 | class Engine < ::Rails::Engine 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/tasks/sqids/rails_tasks.rake: -------------------------------------------------------------------------------- 1 | # desc "Explaining what the task does" 2 | # task :sqids_rails do 3 | # # Task goes here 4 | # end 5 | -------------------------------------------------------------------------------- /test/dummy/app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ApplicationRecord 2 | include Sqids::Rails::Model 3 | 4 | has_sqid 5 | has_sqid :long_sqid, min_length: 24 6 | end 7 | -------------------------------------------------------------------------------- /test/dummy/app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: "from@example.com" 3 | layout "mailer" 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/public/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /test/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /test/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | Rails.application.load_server 7 | -------------------------------------------------------------------------------- /test/dummy/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | if Rails::VERSION::MAJOR < 7 3 | self.abstract_class = true 4 | else 5 | primary_abstract_class 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/setup" 2 | 3 | APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__) 4 | load "rails/tasks/engine.rake" 5 | 6 | load "rails/tasks/statistics.rake" 7 | 8 | require "bundler/gem_tasks" 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /doc/ 3 | /log/*.log 4 | /pkg/ 5 | /tmp/ 6 | /test/dummy/db/*.sqlite3 7 | /test/dummy/db/*.sqlite3-* 8 | /test/dummy/log/*.log 9 | /test/dummy/storage/ 10 | /test/dummy/tmp/ 11 | vendor/bundle 12 | -------------------------------------------------------------------------------- /Appraisals: -------------------------------------------------------------------------------- 1 | appraise "rails-6-1" do 2 | gem "rails", "~> 6.1.0" 3 | end 4 | 5 | appraise "rails-7-0" do 6 | gem "rails", "~> 7.0.0" 7 | end 8 | 9 | appraise "rails-7-1" do 10 | gem "rails", "~> 7.1.0" 11 | end 12 | -------------------------------------------------------------------------------- /test/dummy/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: dummy_production 11 | -------------------------------------------------------------------------------- /test/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative "config/application" 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has. 3 | # allow_browser versions: :modern 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", __dir__) 3 | 4 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) 5 | $LOAD_PATH.unshift File.expand_path("../../../lib", __dir__) 6 | -------------------------------------------------------------------------------- /test/dummy/db/migrate/20240705145551_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration[7.1] 2 | def change 3 | create_table :users do |t| 4 | t.string :sqid 5 | t.string :long_sqid 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/sqids.rb: -------------------------------------------------------------------------------- 1 | Sqids::Rails.configure do |config| 2 | config.min_length = Sqids::DEFAULT_MIN_LENGTH 3 | config.alphabet = Sqids::DEFAULT_ALPHABET 4 | config.blocklist = Sqids::DEFAULT_BLOCKLIST 5 | config.generate_sqid_on = :initialize 6 | end 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec 4 | 5 | gem "rails", "~> 7.2.0" 6 | 7 | gem "puma" 8 | gem "sprockets-rails" 9 | gem "sqlite3", "~> 1.7" 10 | 11 | group :development do 12 | gem "standard", "~> 1.39" 13 | gem "standard-rails", "~> 1.2" 14 | gem "yard", "~> 0.9.37" 15 | end 16 | -------------------------------------------------------------------------------- /test/dummy/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | # Automatically retry jobs that encountered a deadlock 3 | # retry_on ActiveRecord::Deadlocked 4 | 5 | # Most jobs are safe to ignore if the underlying records are no longer available 6 | # discard_on ActiveJob::DeserializationError 7 | end 8 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /gemfiles/rails_6_1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rails", "~> 6.1.0" 6 | gem "puma" 7 | gem "sprockets-rails" 8 | gem "sqlite3", "~> 1.7" 9 | 10 | group :development do 11 | gem "standard", "~> 1.39" 12 | gem "standard-rails", "~> 1.1" 13 | gem "yard", "~> 0.9.36" 14 | end 15 | 16 | gemspec path: "../" 17 | -------------------------------------------------------------------------------- /gemfiles/rails_7_0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rails", "~> 7.0.0" 6 | gem "puma" 7 | gem "sprockets-rails" 8 | gem "sqlite3", "~> 1.7" 9 | 10 | group :development do 11 | gem "standard", "~> 1.39" 12 | gem "standard-rails", "~> 1.1" 13 | gem "yard", "~> 0.9.36" 14 | end 15 | 16 | gemspec path: "../" 17 | -------------------------------------------------------------------------------- /gemfiles/rails_7_1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rails", "~> 7.1.0" 6 | gem "puma" 7 | gem "sprockets-rails" 8 | gem "sqlite3", "~> 1.7" 9 | 10 | group :development do 11 | gem "standard", "~> 1.39" 12 | gem "standard-rails", "~> 1.1" 13 | gem "yard", "~> 0.9.36" 14 | end 15 | 16 | gemspec path: "../" 17 | -------------------------------------------------------------------------------- /gemfiles/rails_7_2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rails", "~> 7.2.0.beta2" 6 | gem "puma" 7 | gem "sprockets-rails" 8 | gem "sqlite3", "~> 1.7" 9 | gem "net-pop", github: "ruby/net-pop" 10 | 11 | group :development do 12 | gem "standard", "~> 1.39" 13 | gem "standard-rails", "~> 1.1" 14 | gem "yard", "~> 0.9.36" 15 | end 16 | 17 | gemspec path: "../" 18 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | pull_request: 8 | types: [opened, synchronize, reopened] 9 | 10 | jobs: 11 | ruby: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: read 15 | checks: write 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: StandardRB Linter 19 | uses: testdouble/standard-ruby-action@main 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | -------------------------------------------------------------------------------- /test/dummy/app/views/pwa/manifest.json.erb: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Dummy", 3 | "icons": [ 4 | { 5 | "src": "/icon.png", 6 | "type": "image/png", 7 | "sizes": "512x512" 8 | }, 9 | { 10 | "src": "/icon.png", 11 | "type": "image/png", 12 | "sizes": "512x512", 13 | "purpose": "maskable" 14 | } 15 | ], 16 | "start_url": "/", 17 | "display": "standalone", 18 | "scope": "/", 19 | "description": "Dummy.", 20 | "theme_color": "red", 21 | "background_color": "red" 22 | } 23 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. 4 | # Use this to limit dissemination of sensitive information. 5 | # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. 6 | Rails.application.config.filter_parameters += [ 7 | :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn 8 | ] 9 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide HTTP permissions policy. For further 4 | # information see: https://developers.google.com/web/updates/2018/06/feature-policy 5 | 6 | # Rails.application.config.permissions_policy do |policy| 7 | # policy.camera :none 8 | # policy.gyroscope :none 9 | # policy.microphone :none 10 | # policy.usb :none 11 | # policy.fullscreen :self 12 | # policy.payment :self, "https://secure.example.com" 13 | # end 14 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = "1.0" 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in the app/assets 11 | # folder are already added. 12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 13 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails gems 3 | # installed from the root of your application. 4 | 5 | ENGINE_ROOT = File.expand_path("..", __dir__) 6 | ENGINE_PATH = File.expand_path("../lib/sqids/rails/engine", __dir__) 7 | APP_PATH = File.expand_path("../test/dummy/config/application", __dir__) 8 | 9 | # Set up gems listed in the Gemfile. 10 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 11 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) 12 | 13 | require "rails/all" 14 | require "rails/engine/commands" 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [Unreleased](https://github.com/tbhb/sqids-rails/compare/v0.2.0...main) 4 | 5 | ## [0.2.0](https://github.com/tbhb/sqids-rails/releases/tag/v0.2.0) - 2024-08-22 6 | 7 | ### Enhancements 8 | 9 | - Only depend on `activerecord` gem instead of `rails` 10 | - Support Rails 7.2.0 11 | 12 | ## [0.1.1](https://github.com/tbhb/sqids-rails/releases/tag/v0.1.1) - 2024-07-05 13 | 14 | ### Fixes 15 | 16 | - Relocate test migration to dummy app ([#2](https://github.com/tbhb/sqids-rails/pull/2)) 17 | 18 | ## [0.1.0](https://github.com/tbhb/sqids-rails/releases/tag/v0.1.0) - 2024-07-05 19 | 20 | - `has_sqid` for auto-generating Sqid columns 21 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # Configure Rails Environment 2 | ENV["RAILS_ENV"] = "test" 3 | 4 | require_relative "../test/dummy/config/environment" 5 | ActiveRecord::Migrator.migrations_paths = [File.expand_path("../test/dummy/db/migrate", __dir__)] 6 | require "rails/test_help" 7 | 8 | # Load fixtures from the engine 9 | if ActiveSupport::TestCase.respond_to?(:fixture_paths=) 10 | ActiveSupport::TestCase.fixture_paths = [File.expand_path("fixtures", __dir__)] 11 | ActionDispatch::IntegrationTest.fixture_paths = ActiveSupport::TestCase.fixture_paths 12 | ActiveSupport::TestCase.file_fixture_path = File.expand_path("fixtures", __dir__) + "/files" 13 | ActiveSupport::TestCase.fixtures :all 14 | end 15 | -------------------------------------------------------------------------------- /test/dummy/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html 3 | 4 | # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. 5 | # Can be used by load balancers and uptime monitors to verify that the app is live. 6 | get "up" => "rails/health#show", :as => :rails_health_check 7 | 8 | # Render dynamic PWA files from app/views/pwa/* 9 | get "service-worker" => "rails/pwa#service_worker", :as => :pwa_service_worker 10 | get "manifest" => "rails/pwa#manifest", :as => :pwa_manifest 11 | 12 | # Defines the root path route ("/") 13 | # root "posts#index" 14 | end 15 | -------------------------------------------------------------------------------- /lib/sqids/rails.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/module/attribute_accessors" 2 | 3 | require "sqids" 4 | require "sqids/rails/version" 5 | require "sqids/rails/engine" 6 | require "sqids/rails/model" 7 | 8 | class Sqids 9 | module Rails 10 | mattr_accessor :alphabet, default: Sqids::DEFAULT_ALPHABET 11 | mattr_accessor :blocklist, default: Sqids::DEFAULT_BLOCKLIST 12 | mattr_accessor :min_length, default: Sqids::DEFAULT_MIN_LENGTH 13 | mattr_accessor :generate_sqid_on, default: :initialize 14 | 15 | def self.configure 16 | yield self 17 | end 18 | 19 | def self.sqids 20 | @sqids ||= Sqids.new(alphabet: alphabet, blocklist: blocklist, min_length: min_length) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= content_for(:title) || "Dummy" %> 5 | 6 | 7 | <%= csrf_meta_tags %> 8 | <%= csp_meta_tag %> 9 | 10 | <%= yield :head %> 11 | 12 | 13 | 14 | 15 | 16 | <%= stylesheet_link_tag "application" %> 17 | 18 | 19 | 20 | <%= yield %> 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, "\\1en" 8 | # inflect.singular /^(ox)en/i, "\\1" 9 | # inflect.irregular "person", "people" 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym "RESTful" 16 | # end 17 | -------------------------------------------------------------------------------- /test/dummy/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rake' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("rake", "rake") 28 | -------------------------------------------------------------------------------- /bin/standardrb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'standardrb' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("standard", "standardrb") 28 | -------------------------------------------------------------------------------- /test/dummy/app/views/pwa/service-worker.js: -------------------------------------------------------------------------------- 1 | // Add a service worker for processing Web Push notifications: 2 | // 3 | // self.addEventListener("push", async (event) => { 4 | // const { title, options } = await event.data.json() 5 | // event.waitUntil(self.registration.showNotification(title, options)) 6 | // }) 7 | // 8 | // self.addEventListener("notificationclick", function(event) { 9 | // event.notification.close() 10 | // event.waitUntil( 11 | // clients.matchAll({ type: "window" }).then((clientList) => { 12 | // for (let i = 0; i < clientList.length; i++) { 13 | // let client = clientList[i] 14 | // let clientPath = (new URL(client.url)).pathname 15 | // 16 | // if (clientPath == event.notification.data.path && "focus" in client) { 17 | // return client.focus() 18 | // } 19 | // } 20 | // 21 | // if (clients.openWindow) { 22 | // return clients.openWindow(event.notification.data.path) 23 | // } 24 | // }) 25 | // ) 26 | // }) 27 | -------------------------------------------------------------------------------- /test/dummy/db/schema.rb: -------------------------------------------------------------------------------- 1 | # This file is auto-generated from the current state of the database. Instead 2 | # of editing this file, please use the migrations feature of Active Record to 3 | # incrementally modify your database, and then regenerate this schema definition. 4 | # 5 | # This file is the source Rails uses to define your schema when running `bin/rails 6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to 7 | # be faster and is potentially less error prone than running all of your 8 | # migrations from scratch. Old migrations may fail to apply correctly if those 9 | # migrations use external dependencies or application code. 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema[7.1].define(version: 2024_07_05_145551) do 14 | create_table "users", force: :cascade do |t| 15 | t.string "sqid" 16 | t.string "long_sqid" 17 | t.datetime "created_at", null: false 18 | t.datetime "updated_at", null: false 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /test/dummy/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization and 2 | # are automatically loaded by Rails. If you want to use locales other than 3 | # English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t "hello" 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t("hello") %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more about the API, please read the Rails Internationalization guide 20 | # at https://guides.rubyonrails.org/i18n.html. 21 | # 22 | # Be aware that YAML interprets the following case-insensitive strings as 23 | # booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings 24 | # must be quoted to be interpreted as strings. For example: 25 | # 26 | # en: 27 | # "yes": yup 28 | # enabled: "ON" 29 | 30 | en: 31 | hello: "Hello world" 32 | -------------------------------------------------------------------------------- /sqids-rails.gemspec: -------------------------------------------------------------------------------- 1 | require_relative "lib/sqids/rails/version" 2 | 3 | Gem::Specification.new do |spec| 4 | spec.name = "sqids-rails" 5 | spec.version = Sqids::Rails::VERSION 6 | spec.authors = ["Tony Burns"] 7 | spec.email = ["tony@tonyburns.net"] 8 | spec.homepage = "https://github.com/tbhb/sqids-rails" 9 | spec.summary = "Short, unique, and human-readable IDs for ActiveRecord models with Sqids." 10 | spec.description = spec.summary 11 | spec.license = "MIT" 12 | 13 | spec.metadata["homepage_uri"] = spec.homepage 14 | spec.metadata["source_code_uri"] = "https://github.com/tbhb/sqids-rails" 15 | spec.metadata["changelog_uri"] = "https://github.com/tbhb/sqids-rails/blob/main/sqids-rails/CHANGELOG.md" 16 | 17 | spec.files = Dir.chdir(File.expand_path(__dir__)) do 18 | Dir["{app,config,db,lib}/**/*", "LICENSE.txt", "Rakefile", "README.md"] 19 | end 20 | 21 | spec.required_ruby_version = ">= 3.1" 22 | 23 | spec.add_dependency "activerecord", ">= 6.1.0" 24 | spec.add_dependency "sqids", "~> 0.2" 25 | 26 | spec.add_development_dependency "appraisal" 27 | end 28 | -------------------------------------------------------------------------------- /test/dummy/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite. Versions 3.8.0 and up are supported. 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem "sqlite3" 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: storage/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: storage/test.sqlite3 22 | 23 | 24 | # SQLite3 write its data on the local filesystem, as such it requires 25 | # persistent disks. If you are deploying to a managed service, you should 26 | # make sure it provides disk persistence, as many don't. 27 | # 28 | # Similarly, if you deploy your application as a Docker container, you must 29 | # ensure the database is located in a persisted volume. 30 | production: 31 | <<: *default 32 | # database: path/to/persistent/storage/production.sqlite3 33 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 Tony Burns 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Tests 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | pull_request: 8 | types: [opened, synchronize, reopened] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | name: Ruby ${{ matrix.ruby }} 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | ruby: 18 | - "3.1" 19 | - "3.2" 20 | - "3.3" 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Set up Ruby 25 | uses: ruby/setup-ruby@v1 26 | with: 27 | ruby-version: ${{ matrix.ruby }} 28 | bundler-cache: true 29 | - name: Install Appraisal dependencies 30 | run: bundle exec appraisal install 31 | - name: Set up the database 32 | run: bundle exec rails db:setup 33 | - name: Run tests 34 | run: bundle exec rails test 35 | - name: Appraise Rails 6.1 36 | run: bundle exec appraisal rails-6-1 rails test 37 | - name: Appraise Rails 7.0 38 | run: bundle exec appraisal rails-7-0 rails test 39 | - name: Appraise Rails 7.1 40 | run: bundle exec appraisal rails-7-1 rails test 41 | -------------------------------------------------------------------------------- /test/dummy/config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative "boot" 2 | 3 | require "rails/all" 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module Dummy 10 | class Application < Rails::Application 11 | config.load_defaults Rails::VERSION::STRING.to_f 12 | 13 | # For compatibility with applications that use this config 14 | config.action_controller.include_all_helpers = false 15 | 16 | # Please, add to the `ignore` list any other `lib` subdirectories that do 17 | # not contain `.rb` files, or that should not be reloaded or eager loaded. 18 | # Common ones are `templates`, `generators`, or `middleware`, for example. 19 | # config.autoload_lib(ignore: %w[assets tasks]) 20 | 21 | # Configuration for the application, engines, and railties goes here. 22 | # 23 | # These settings can be overridden in specific environments using the files 24 | # in config/environments, which are processed later. 25 | # 26 | # config.time_zone = "Central Time (US & Canada)" 27 | # config.eager_load_paths << Rails.root.join("extras") 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy. 4 | # See the Securing Rails Applications Guide for more information: 5 | # https://guides.rubyonrails.org/security.html#content-security-policy-header 6 | 7 | # Rails.application.configure do 8 | # config.content_security_policy do |policy| 9 | # policy.default_src :self, :https 10 | # policy.font_src :self, :https, :data 11 | # policy.img_src :self, :https, :data 12 | # policy.object_src :none 13 | # policy.script_src :self, :https 14 | # policy.style_src :self, :https 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | # 19 | # # Generate session nonces for permitted importmap, inline scripts, and inline styles. 20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 21 | # config.content_security_policy_nonce_directives = %w(script-src style-src) 22 | # 23 | # # Report violations without enforcing the policy. 24 | # # config.content_security_policy_report_only = true 25 | # end 26 | -------------------------------------------------------------------------------- /test/dummy/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | APP_ROOT = File.expand_path("..", __dir__) 5 | APP_NAME = "dummy" 6 | 7 | def system!(*) 8 | system(*, exception: true) 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to set up or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts "== Installing dependencies ==" 17 | system! "gem install bundler --conservative" 18 | system("bundle check") || system!("bundle install") 19 | 20 | # puts "\n== Copying sample files ==" 21 | # unless File.exist?("config/database.yml") 22 | # FileUtils.cp "config/database.yml.sample", "config/database.yml" 23 | # end 24 | 25 | puts "\n== Preparing database ==" 26 | system! "bin/rails db:prepare" 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! "bin/rails log:clear tmp:clear" 30 | 31 | puts "\n== Restarting application server ==" 32 | system! "bin/rails restart" 33 | 34 | # puts "\n== Configuring puma-dev ==" 35 | # system "ln -nfs #{APP_ROOT} ~/.puma-dev/#{APP_NAME}" 36 | # system "curl -Is https://#{APP_NAME}.test/up | head -n 1" 37 | end 38 | -------------------------------------------------------------------------------- /test/dummy/config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket-<%= Rails.env %> 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket-<%= Rails.env %> 23 | 24 | # Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name-<%= Rails.env %> 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported versions of Ruby and Rails 4 | 5 | This gem supports currently maintained versions of Ruby and Rails, according to their respective maintenance policies. 6 | 7 | ### Ruby Versions 8 | 9 | | Version | Supported | 10 | | ------- | ------------------ | 11 | | 3.3.x | :white_check_mark: | 12 | | 3.2.x | :white_check_mark: | 13 | | 3.1.x | :white_check_mark: | 14 | | < 3.1 | :x: | 15 | 16 | ### Rails Versions 17 | 18 | | Version | Supported | 19 | | ------- | ------------------ | 20 | | 7.1.x | :white_check_mark: | 21 | | 7.0.x | :white_check_mark: | 22 | | 6.1.x | :white_check_mark: | 23 | | < 6.1 | :x: | 24 | 25 | ## Reporting a Vulnerability 26 | 27 | If you discover a security vulnerability within sqids-rails, please send an email to . All security vulnerabilities will be promptly addressed. 28 | 29 | Please do not publicly disclose the issue until it has been addressed by the maintainers. 30 | 31 | ## Security Updates 32 | 33 | Security updates will be released as soon as possible after they are developed and tested. We recommend always using the latest version of sqids-rails to ensure you have all security patches. 34 | 35 | ## Code of Conduct 36 | 37 | This project adheres to a [code of conduct](CODE_OF_CONDUCT.md). By participating in this project, you are expected to uphold this code. 38 | -------------------------------------------------------------------------------- /test/dummy/public/406-unsupported-browser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Your browser is not supported (406) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

Your browser is not supported.

62 |

Please upgrade your browser to continue.

63 |
64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /test/dummy/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /test/dummy/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/dummy/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/dummy/config/puma.rb: -------------------------------------------------------------------------------- 1 | # This configuration file will be evaluated by Puma. The top-level methods that 2 | # are invoked here are part of Puma's configuration DSL. For more information 3 | # about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. 4 | 5 | # Puma starts a configurable number of processes (workers) and each process 6 | # serves each request in a thread from an internal thread pool. 7 | # 8 | # The ideal number of threads per worker depends both on how much time the 9 | # application spends waiting for IO operations and on how much you wish to 10 | # to prioritize throughput over latency. 11 | # 12 | # As a rule of thumb, increasing the number of threads will increase how much 13 | # traffic a given process can handle (throughput), but due to CRuby's 14 | # Global VM Lock (GVL) it has diminishing returns and will degrade the 15 | # response time (latency) of the application. 16 | # 17 | # The default is set to 3 threads as it's deemed a decent compromise between 18 | # throughput and latency for the average Rails application. 19 | # 20 | # Any libraries that use a connection pool or another resource pool should 21 | # be configured to provide at least as many connections as the number of 22 | # threads. This includes Active Record's `pool` parameter in `database.yml`. 23 | threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) 24 | threads threads_count, threads_count 25 | 26 | # Specifies the `environment` that Puma will run in. 27 | rails_env = ENV.fetch("RAILS_ENV", "development") 28 | environment rails_env 29 | 30 | case rails_env 31 | when "production" 32 | # If you are running more than 1 thread per process, the workers count 33 | # should be equal to the number of processors (CPU cores) in production. 34 | # 35 | # Automatically detect the number of available processors in production. 36 | require "concurrent-ruby" 37 | workers_count = Integer(ENV.fetch("WEB_CONCURRENCY") { Concurrent.available_processor_count }) 38 | workers workers_count if workers_count > 1 39 | 40 | preload_app! 41 | when "development" 42 | # Specifies a very generous `worker_timeout` so that the worker 43 | # isn't killed by Puma when suspended by a debugger. 44 | worker_timeout 3600 45 | end 46 | 47 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 48 | port ENV.fetch("PORT", 3000) 49 | 50 | # Allow puma to be restarted by `bin/rails restart` command. 51 | plugin :tmp_restart 52 | 53 | # Only use a pidfile when requested 54 | pidfile ENV["PIDFILE"] if ENV["PIDFILE"] 55 | -------------------------------------------------------------------------------- /test/dummy/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # In the development environment your application's code is reloaded any time 7 | # it changes. This slows down response time but is perfect for development 8 | # since you don't have to restart the web server when you make code changes. 9 | config.enable_reloading = true 10 | 11 | # Do not eager load code on boot. 12 | config.eager_load = false 13 | 14 | # Show full error reports. 15 | config.consider_all_requests_local = true 16 | 17 | # Enable server timing. 18 | config.server_timing = true 19 | 20 | # Enable/disable caching. By default caching is disabled. 21 | # Run rails dev:cache to toggle caching. 22 | if Rails.root.join("tmp/caching-dev.txt").exist? 23 | config.action_controller.perform_caching = true 24 | config.action_controller.enable_fragment_cache_logging = true 25 | 26 | config.cache_store = :memory_store 27 | config.public_file_server.headers = {"Cache-Control" => "public, max-age=#{2.days.to_i}"} 28 | else 29 | config.action_controller.perform_caching = false 30 | 31 | config.cache_store = :null_store 32 | end 33 | 34 | # Store uploaded files on the local file system (see config/storage.yml for options). 35 | config.active_storage.service = :local 36 | 37 | # Don't care if the mailer can't send. 38 | config.action_mailer.raise_delivery_errors = false 39 | 40 | config.action_mailer.perform_caching = false 41 | 42 | config.action_mailer.default_url_options = {host: "localhost", port: 3000} 43 | 44 | # Print deprecation notices to the Rails logger. 45 | config.active_support.deprecation = :log 46 | 47 | # Raise exceptions for disallowed deprecations. 48 | config.active_support.disallowed_deprecation = :raise 49 | 50 | # Tell Active Support which deprecation messages to disallow. 51 | config.active_support.disallowed_deprecation_warnings = [] 52 | 53 | # Raise an error on page load if there are pending migrations. 54 | config.active_record.migration_error = :page_load 55 | 56 | # Highlight code that triggered database queries in logs. 57 | config.active_record.verbose_query_logs = true 58 | 59 | # Highlight code that enqueued background job in logs. 60 | config.active_job.verbose_enqueue_logs = true 61 | 62 | # Suppress logger output for asset requests. 63 | config.assets.quiet = true 64 | 65 | # Raises error for missing translations. 66 | # config.i18n.raise_on_missing_translations = true 67 | 68 | # Annotate rendered view with file names. 69 | config.action_view.annotate_rendered_view_with_filenames = true 70 | 71 | # Uncomment if you wish to allow Action Cable access from any origin. 72 | # config.action_cable.disable_request_forgery_protection = true 73 | 74 | # Raise error when a before_action's only/except options reference missing actions. 75 | config.action_controller.raise_on_missing_callback_actions = true if Rails::VERSION::MAJOR >= 7 && Rails::VERSION::MINOR >= 1 76 | end 77 | -------------------------------------------------------------------------------- /test/dummy/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | 8 | Rails.application.configure do 9 | # Settings specified here will take precedence over those in config/application.rb. 10 | 11 | # While tests run files are not watched, reloading is not necessary. 12 | config.enable_reloading = false 13 | 14 | # Eager loading loads your entire application. When running a single test locally, 15 | # this is usually not necessary, and can slow down your test suite. However, it's 16 | # recommended that you enable it in continuous integration systems to ensure eager 17 | # loading is working properly before deploying your code. 18 | config.eager_load = ENV["CI"].present? 19 | 20 | # Configure public file server for tests with Cache-Control for performance. 21 | config.public_file_server.headers = {"Cache-Control" => "public, max-age=#{1.hour.to_i}"} 22 | 23 | # Show full error reports and disable caching. 24 | config.consider_all_requests_local = true 25 | config.action_controller.perform_caching = false 26 | config.cache_store = :null_store 27 | 28 | # Render exception templates for rescuable exceptions and raise for other exceptions. 29 | config.action_dispatch.show_exceptions = :rescuable 30 | 31 | # Disable request forgery protection in test environment. 32 | config.action_controller.allow_forgery_protection = false 33 | 34 | # Store uploaded files on the local file system in a temporary directory. 35 | config.active_storage.service = :test 36 | 37 | config.action_mailer.perform_caching = false 38 | 39 | # Tell Action Mailer not to deliver emails to the real world. 40 | # The :test delivery method accumulates sent emails in the 41 | # ActionMailer::Base.deliveries array. 42 | config.action_mailer.delivery_method = :test 43 | 44 | # Unlike controllers, the mailer instance doesn't have any context about the 45 | # incoming request so you'll need to provide the :host parameter yourself. 46 | config.action_mailer.default_url_options = {host: "www.example.com"} 47 | 48 | # Print deprecation notices to the stderr. 49 | config.active_support.deprecation = :stderr 50 | 51 | # Raise exceptions for disallowed deprecations. 52 | config.active_support.disallowed_deprecation = :raise 53 | 54 | # Tell Active Support which deprecation messages to disallow. 55 | config.active_support.disallowed_deprecation_warnings = [] 56 | 57 | # Raises error for missing translations. 58 | # config.i18n.raise_on_missing_translations = true 59 | 60 | # Annotate rendered view with file names. 61 | # config.action_view.annotate_rendered_view_with_filenames = true 62 | 63 | # Raise error when a before_action's only/except options reference missing actions. 64 | config.action_controller.raise_on_missing_callback_actions = true if Rails::VERSION::MAJOR >= 7 && Rails::VERSION::MINOR >= 1 65 | end 66 | -------------------------------------------------------------------------------- /test/lib/sqids/rails/model_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class Sqids::Rails::ModelTest < ActiveSupport::TestCase 4 | setup do 5 | @user = User.new 6 | end 7 | 8 | test "sqid attributes are generated for specified attributes and persisted on save" do 9 | @user.save 10 | assert_not_nil @user.sqid 11 | assert_not_nil @user.long_sqid 12 | assert @user.sqid.length >= Sqids::Rails.min_length 13 | assert @user.long_sqid.length >= 24 14 | end 15 | 16 | test "generating sqid on initialize does not affect reading from the sqid" do 17 | model = Class.new(ApplicationRecord) do 18 | include Sqids::Rails::Model 19 | 20 | self.table_name = "users" 21 | has_sqid on: :initialize 22 | end 23 | 24 | sqid = "abc123" 25 | user = model.create!(sqid: sqid) 26 | 27 | assert_equal sqid, user.sqid 28 | assert_equal sqid, user.reload.sqid 29 | assert_equal sqid, model.find(user.id).sqid 30 | end 31 | 32 | test "generating sqid on initialize happens only once" do 33 | model = Class.new(ApplicationRecord) do 34 | include Sqids::Rails::Model 35 | 36 | self.table_name = "users" 37 | has_sqid on: :initialize 38 | end 39 | 40 | sqid = " " 41 | 42 | user = model.new 43 | user.update!(sqid: sqid) 44 | 45 | assert_equal sqid, user.sqid 46 | assert_equal sqid, user.reload.sqid 47 | assert_equal sqid, model.find(user.id).sqid 48 | end 49 | 50 | test "generating sqid on initialize is skipped if column was not selected" do 51 | model = Class.new(ApplicationRecord) do 52 | include Sqids::Rails::Model 53 | 54 | self.table_name = "users" 55 | has_sqid on: :initialize 56 | end 57 | 58 | model.create! 59 | assert_nothing_raised do 60 | model.select(:id).last 61 | end 62 | end 63 | 64 | test "regenerating the sqid" do 65 | @user.save 66 | old_sqid = @user.sqid 67 | old_long_sqid = @user.long_sqid 68 | @user.regenerate_sqid 69 | @user.regenerate_long_sqid 70 | 71 | assert_not_equal old_sqid, @user.sqid 72 | assert_not_equal old_long_sqid, @user.long_sqid 73 | 74 | assert @user.sqid.length >= Sqids::Rails.min_length 75 | assert @user.long_sqid.length >= 24 76 | end 77 | 78 | test "sqid value not overwritten when present" do 79 | @user.sqid = "custom-sqid" 80 | @user.save 81 | 82 | assert_equal "custom-sqid", @user.sqid 83 | end 84 | 85 | test "alphabet must be at least 3 characters" do 86 | assert_raises(Sqids::Rails::Model::AlphabetError) do 87 | @user.class_eval do 88 | has_sqid alphabet: "ab" 89 | end 90 | end 91 | end 92 | 93 | test "alphabet cannot contain multibyte characters" do 94 | assert_raises(Sqids::Rails::Model::AlphabetError) do 95 | @user.class_eval do 96 | has_sqid alphabet: "abé" 97 | end 98 | end 99 | end 100 | 101 | test "alphabet must contain unique characters" do 102 | assert_raises(Sqids::Rails::Model::AlphabetError) do 103 | @user.class_eval do 104 | has_sqid alphabet: "aabcdefg" 105 | end 106 | end 107 | end 108 | 109 | test "minimum length must be between 0 and 255" do 110 | assert_raises(Sqids::Rails::Model::MinimumLengthError) do 111 | @user.class_eval do 112 | has_sqid min_length: -1 113 | end 114 | end 115 | assert_raises(Sqids::Rails::Model::MinimumLengthError) do 116 | @user.class_eval do 117 | has_sqid min_length: 256 118 | end 119 | end 120 | end 121 | 122 | test "sqid on callback" do 123 | model = Class.new(ApplicationRecord) do 124 | include Sqids::Rails::Model 125 | 126 | self.table_name = "users" 127 | has_sqid on: :initialize 128 | end 129 | 130 | user = model.new 131 | 132 | assert_predicate user.sqid, :present? 133 | end 134 | 135 | test "sqid calls the setter method" do 136 | model = Class.new(ApplicationRecord) do 137 | include Sqids::Rails::Model 138 | 139 | self.table_name = "users" 140 | has_sqid on: :initialize 141 | 142 | attr_accessor :modified_sqid 143 | 144 | def sqid=(value) 145 | super 146 | self.modified_sqid = "#{value}_modified" 147 | end 148 | end 149 | 150 | user = model.new 151 | 152 | assert_equal "#{user.sqid}_modified", user.modified_sqid 153 | end 154 | end 155 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | branches: [ "main" ] 19 | schedule: 20 | - cron: '45 7 * * 2' 21 | 22 | jobs: 23 | analyze: 24 | name: Analyze (${{ matrix.language }}) 25 | # Runner size impacts CodeQL analysis time. To learn more, please see: 26 | # - https://gh.io/recommended-hardware-resources-for-running-codeql 27 | # - https://gh.io/supported-runners-and-hardware-resources 28 | # - https://gh.io/using-larger-runners (GitHub.com only) 29 | # Consider using larger runners or machines with greater resources for possible analysis time improvements. 30 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 31 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 32 | permissions: 33 | # required for all workflows 34 | security-events: write 35 | 36 | # required to fetch internal or private CodeQL packs 37 | packages: read 38 | 39 | # only required for workflows in private repositories 40 | actions: read 41 | contents: read 42 | 43 | strategy: 44 | fail-fast: false 45 | matrix: 46 | include: 47 | - language: ruby 48 | build-mode: none 49 | # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' 50 | # Use `c-cpp` to analyze code written in C, C++ or both 51 | # Use 'java-kotlin' to analyze code written in Java, Kotlin or both 52 | # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both 53 | # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, 54 | # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. 55 | # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how 56 | # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages 57 | steps: 58 | - name: Checkout repository 59 | uses: actions/checkout@v4 60 | 61 | # Initializes the CodeQL tools for scanning. 62 | - name: Initialize CodeQL 63 | uses: github/codeql-action/init@v3 64 | with: 65 | languages: ${{ matrix.language }} 66 | build-mode: ${{ matrix.build-mode }} 67 | # If you wish to specify custom queries, you can do so here or in a config file. 68 | # By default, queries listed here will override any specified in a config file. 69 | # Prefix the list here with "+" to use these queries and those in the config file. 70 | 71 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 72 | # queries: security-extended,security-and-quality 73 | 74 | # If the analyze step fails for one of the languages you are analyzing with 75 | # "We were unable to automatically build your code", modify the matrix above 76 | # to set the build mode to "manual" for that language. Then modify this step 77 | # to build your code. 78 | # ℹ️ Command-line programs to run using the OS shell. 79 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 80 | - if: matrix.build-mode == 'manual' 81 | shell: bash 82 | run: | 83 | echo 'If you are using a "manual" build mode for one or more of the' \ 84 | 'languages you are analyzing, replace this with the commands to build' \ 85 | 'your code, for example:' 86 | echo ' make bootstrap' 87 | echo ' make release' 88 | exit 1 89 | 90 | - name: Perform CodeQL Analysis 91 | uses: github/codeql-action/analyze@v3 92 | with: 93 | category: "/language:${{matrix.language}}" 94 | -------------------------------------------------------------------------------- /lib/sqids/rails/model.rb: -------------------------------------------------------------------------------- 1 | class Sqids 2 | module Rails 3 | module Model 4 | class AlphabetError < StandardError; end 5 | 6 | class MinimumLengthError < StandardError; end 7 | 8 | extend ActiveSupport::Concern 9 | 10 | module ClassMethods 11 | # Example using #has_sqid: 12 | # 13 | # # Schema: User(sqid:string, long_sqid:string) 14 | # class User < ApplicationRecord 15 | # include Sqids::Rails::Model 16 | # 17 | # has_sqid 18 | # has_sqid :long_sqid, min_length: 24 19 | # end 20 | # 21 | # user = User.new 22 | # user.save 23 | # user.sqid # => "lzNKgEb6ZuaU" 24 | # user.sqid_long # => "4y3SVm9M2aV8Olu6p4zZoGij" 25 | # user.regenerate_sqid 26 | # user.regenerate_long_sqid 27 | # 28 | # +SecureRandom.random_number(Sqids.max_value)+ is used to generate the random number to encode. 29 | # 30 | # Note that it's still possible to generate a race condition in the database in the same way that 31 | # {validates_uniqueness_of}[https://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_uniqueness_of] 32 | # can. You're encouraged to add a unique index in the database to deal with this even more unlikely scenario. 33 | # 34 | # See the {Sqids Ruby}[https://github.com/sqids/sqids-ruby] documentation for more information on the options. 35 | # 36 | # === Options 37 | # 38 | # [:alphabet] 39 | # The alphabet to use for encoding. Default is +Sqids::Rails.alphabet+. 40 | # The minimum alphabet length is 3 characters. 41 | # The alphabet cannot contain any multibyte characters. 42 | # 43 | # [:blocklist] 44 | # The blocklist to use for encoding. Default is +Sqids::Rails.blocklist+. 45 | # 46 | # [:min_length] 47 | # The minimum length of the generated sqid, from 0-255. Default is +Sqids::Rails.min_length+. Sqids cannot 48 | # generate IDs up to a certain length, only at least a certain length. 49 | # 50 | # [:on] 51 | # The callback when the value is generated. When called with on: :initialize, the value is generated 52 | # in an after_initialize callback, otherwise the value will be used in a before_ callback. 53 | # When not specified, +:on+ will use the value of Sqids::Rails.generate_sqid_on, which defaults to 54 | # +:initialize+. 55 | def has_sqid( 56 | attribute = :sqid, 57 | alphabet: Sqids::Rails.alphabet, 58 | blocklist: Sqids::Rails.blocklist, 59 | min_length: Sqids::Rails.min_length, 60 | on: Sqids::Rails.generate_sqid_on 61 | ) 62 | if alphabet.length < 3 63 | raise AlphabetError, "Sqid requires an alphabet of at least 3 characters" 64 | end 65 | 66 | if alphabet.each_char.any? { |char| char.bytesize > 1 } 67 | raise AlphabetError, "Sqid alphabet cannot contain multibyte characters" 68 | end 69 | 70 | if alphabet.chars.uniq.length != alphabet.length 71 | raise AlphabetError, "Sqid alphabet must contain unique characters" 72 | end 73 | 74 | if min_length < 0 || min_length > 255 75 | raise MinimumLengthError, "Sqid requires a minimum length between 0 and 255 characters" 76 | end 77 | 78 | define_method(:"regenerate_#{attribute}") do 79 | update!( 80 | attribute => self.class.generate_unique_sqid( 81 | alphabet: alphabet, blocklist: blocklist, min_length: min_length 82 | ) 83 | ) 84 | end 85 | set_callback(on, (on == :initialize) ? :after : :before) do 86 | if new_record? && !query_attribute(attribute) 87 | send( 88 | :"#{attribute}=", 89 | self.class.generate_unique_sqid(alphabet: alphabet, blocklist: blocklist, min_length: min_length) 90 | ) 91 | end 92 | end 93 | end 94 | 95 | def generate_unique_sqid( 96 | alphabet: Sqids::Rails.alphabet, blocklist: Sqids::Rails.blocklist, min_length: Sqids::Rails.min_length 97 | ) 98 | @sqids ||= {} 99 | @sqids[[alphabet, blocklist, min_length]] ||= Sqids.new( 100 | alphabet: alphabet, blocklist: blocklist, min_length: min_length 101 | ) 102 | @sqids[[alphabet, blocklist, min_length]].encode([SecureRandom.random_number(Sqids.max_value)]) 103 | end 104 | end 105 | end 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /test/dummy/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # Code is not reloaded between requests. 7 | config.enable_reloading = false 8 | 9 | # Eager load code on boot. This eager loads most of Rails and 10 | # your application in memory, allowing both threaded web servers 11 | # and those relying on copy on write to perform better. 12 | # Rake tasks automatically ignore this option for performance. 13 | config.eager_load = true 14 | 15 | # Full error reports are disabled and caching is turned on. 16 | config.consider_all_requests_local = false 17 | config.action_controller.perform_caching = true 18 | 19 | # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment 20 | # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). 21 | # config.require_master_key = true 22 | 23 | # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead. 24 | # config.public_file_server.enabled = false 25 | 26 | # Compress CSS using a preprocessor. 27 | # config.assets.css_compressor = :sass 28 | 29 | # Do not fall back to assets pipeline if a precompiled asset is missed. 30 | config.assets.compile = false 31 | 32 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 33 | # config.asset_host = "http://assets.example.com" 34 | 35 | # Specifies the header that your server uses for sending files. 36 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache 37 | # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX 38 | 39 | # Store uploaded files on the local file system (see config/storage.yml for options). 40 | config.active_storage.service = :local 41 | 42 | # Mount Action Cable outside main process or domain. 43 | # config.action_cable.mount_path = nil 44 | # config.action_cable.url = "wss://example.com/cable" 45 | # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] 46 | 47 | # Assume all access to the app is happening through a SSL-terminating reverse proxy. 48 | # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. 49 | # config.assume_ssl = true 50 | 51 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 52 | config.force_ssl = true 53 | # Skip http-to-https redirect for the default health check endpoint. 54 | # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } 55 | 56 | # Log to STDOUT by default 57 | config.logger = ActiveSupport::Logger.new($stdout) 58 | .tap { |logger| logger.formatter = ::Logger::Formatter.new } 59 | .then { |logger| ActiveSupport::TaggedLogging.new(logger) } 60 | 61 | # Prepend all log lines with the following tags. 62 | config.log_tags = [:request_id] 63 | 64 | # "info" includes generic and useful information about system operation, but avoids logging too much 65 | # information to avoid inadvertent exposure of personally identifiable information (PII). If you 66 | # want to log everything, set the level to "debug". 67 | config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") 68 | 69 | # Use a different cache store in production. 70 | # config.cache_store = :mem_cache_store 71 | 72 | # Use a real queuing backend for Active Job (and separate queues per environment). 73 | # config.active_job.queue_adapter = :resque 74 | # config.active_job.queue_name_prefix = "dummy_production" 75 | 76 | config.action_mailer.perform_caching = false 77 | 78 | # Ignore bad email addresses and do not raise email delivery errors. 79 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 80 | # config.action_mailer.raise_delivery_errors = false 81 | 82 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 83 | # the I18n.default_locale when a translation cannot be found). 84 | config.i18n.fallbacks = true 85 | 86 | # Don't log any deprecations. 87 | config.active_support.report_deprecations = false 88 | 89 | # Do not dump schema after migrations. 90 | config.active_record.dump_schema_after_migration = false 91 | 92 | # Enable DNS rebinding protection and other `Host` header attacks. 93 | # config.hosts = [ 94 | # "example.com", # Allow requests from example.com 95 | # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` 96 | # ] 97 | # Skip DNS rebinding protection for the default health check endpoint. 98 | # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } 99 | end 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sqids-rails 2 | 3 | ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/tbhb/sqids-rails/tests.yml) 4 | ![Gem Version](https://img.shields.io/gem/v/sqids-rails) 5 | 6 | [Sqids](https://sqids.org) (formerly [Hashids](https://github.com/hashids)) integration for [Ruby on Rails](https://rubyonrails.org). 7 | 8 | From [sqids-ruby](https://github.com/sqids/sqids-ruby): 9 | 10 | > [Sqids](https://sqids.org/ruby) _(pronounced "squids")_ is a small library that lets you generate unique IDs from numbers. It's good for link shortening, fast & URL-safe ID generation and decoding back into numbers for quicker database lookups. 11 | > 12 | > Features: 13 | > 14 | > - Encode multiple numbers - generate short IDs from one or several non-negative numbers 15 | > - Quick decoding - easily decode IDs back into numbers 16 | > - Unique IDs - generate unique IDs by shuffling the alphabet once 17 | > - ID padding - provide minimum length to make IDs more uniform 18 | > - URL safe - auto-generated IDs do not contain common profanity 19 | > - Randomized output - Sequential input provides nonconsecutive IDs 20 | > - Many implementations - Support for 40+ programming languages 21 | 22 | ## Getting started 23 | 24 | Run `bundle add sqids-rails` or add this line to your application's `Gemfile`: 25 | 26 | ```ruby 27 | gem 'sqids-rails' 28 | ``` 29 | 30 | And then execute: 31 | 32 | ```shell 33 | bundle 34 | ``` 35 | 36 | ## Usage 37 | 38 | Add auto-generated sqids columns to your ActiveRecord models with `has_sqid`: 39 | 40 | ```ruby 41 | # Schema: users(sqid:string, long_sqid:string) 42 | class User < ApplicationRecord 43 | include Sqids::Rails::Model 44 | 45 | has_sqid 46 | has_sqid :long_sqid, min_length: 24 47 | end 48 | 49 | user = User.new 50 | user.save 51 | user.sqid # => "lzNKgEb6ZuaU" 52 | user.sqid_long # => "4y3SVm9M2aV8Olu6p4zZoGij" 53 | user.regenerate_sqid 54 | user.regenerate_long_sqid 55 | ``` 56 | 57 | `has_sqid` follows the same behavior as ActiveRecord's built-in [has_secure_token](https://api.rubyonrails.org/classes/ActiveRecord/SecureToken/ClassMethods.html#method-i-has_secure_token) 58 | 59 | Use a custom attribute name (the default is `sqid`): 60 | 61 | ```ruby 62 | has_sqid :uid 63 | ``` 64 | 65 | Enforce a _minimum length_ for generated IDs: 66 | 67 | ```ruby 68 | has_sqid min_length: 24 69 | ``` 70 | 71 | Provide a custom alphabet for generated IDs: 72 | 73 | ```ruby 74 | has_sqid alphabet: "FxnXM1kBN6cuhsAvjW3Co7l2RePyY8DwaU04Tzt9fHQrqSVKdpimLGIJOgb5ZE" 75 | ``` 76 | 77 | Prevent specific words from appearing anywhere in generated IDs: 78 | 79 | ```ruby 80 | has_sqid blocklist: Set.new(%w[86Rf07]) 81 | ``` 82 | 83 | ## Performance considerations 84 | 85 | - Consider adding indexes (with uniqueness constraints) when finding records by Sqid. 86 | - The size of the alphabet can impact performance. A larger alphabet allows for shorter Sqids but slightly increase generation time. 87 | - The size of the blocklist can impact performance, as each generated ID is checked against the blocklist. 88 | 89 | ## Roadmap 90 | 91 | - [x] `has_sqid` for auto-generating Sqid columns 92 | - [ ] Extensions to [ActiveRecord::FinderMethods](https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html) and [ActiveRecord::Associations::CollectionProxy](https://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-find) to find records with a Sqid-encoded primary key 93 | 94 | ## Contributing 95 | 96 | Bug reports and pull requests are welcome on [GitHub](https://github.com/tbhb/sqids-rails). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/tbhb/sqids-rails/blob/main/CODE_OF_CONDUCT.md). 97 | 98 | ## Acknowledgements 99 | 100 | Thanks to Ivan Akimov ([@4kimov](https://github.com/4kimov)) for creating and maintaining Sqids and [sqids-ruby](https://github.com/sqids/sqids-ruby), and Roberto Miranda ([@robertomiranda](https://github.com/robertomiranda)) for `has_secure_token`. 101 | 102 | ## MIT License 103 | 104 | Copyright (c) 2024 Anthony Burns 105 | 106 | Permission is hereby granted, free of charge, to any person obtaining a copy 107 | of this software and associated documentation files (the "Software"), to deal 108 | in the Software without restriction, including without limitation the rights 109 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 110 | copies of the Software, and to permit persons to whom the Software is 111 | furnished to do so, subject to the following conditions: 112 | 113 | The above copyright notice and this permission notice shall be included in 114 | all copies or substantial portions of the Software. 115 | 116 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 117 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 118 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 119 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 120 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 121 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 122 | THE SOFTWARE. 123 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual 10 | identity and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official email address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.1, available at 119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 126 | [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations 133 | -------------------------------------------------------------------------------- /gemfiles/rails_6_1.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | sqids-rails (0.2.0) 5 | activerecord (>= 6.1.0) 6 | sqids (~> 0.2) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | actioncable (6.1.7.8) 12 | actionpack (= 6.1.7.8) 13 | activesupport (= 6.1.7.8) 14 | nio4r (~> 2.0) 15 | websocket-driver (>= 0.6.1) 16 | actionmailbox (6.1.7.8) 17 | actionpack (= 6.1.7.8) 18 | activejob (= 6.1.7.8) 19 | activerecord (= 6.1.7.8) 20 | activestorage (= 6.1.7.8) 21 | activesupport (= 6.1.7.8) 22 | mail (>= 2.7.1) 23 | actionmailer (6.1.7.8) 24 | actionpack (= 6.1.7.8) 25 | actionview (= 6.1.7.8) 26 | activejob (= 6.1.7.8) 27 | activesupport (= 6.1.7.8) 28 | mail (~> 2.5, >= 2.5.4) 29 | rails-dom-testing (~> 2.0) 30 | actionpack (6.1.7.8) 31 | actionview (= 6.1.7.8) 32 | activesupport (= 6.1.7.8) 33 | rack (~> 2.0, >= 2.0.9) 34 | rack-test (>= 0.6.3) 35 | rails-dom-testing (~> 2.0) 36 | rails-html-sanitizer (~> 1.0, >= 1.2.0) 37 | actiontext (6.1.7.8) 38 | actionpack (= 6.1.7.8) 39 | activerecord (= 6.1.7.8) 40 | activestorage (= 6.1.7.8) 41 | activesupport (= 6.1.7.8) 42 | nokogiri (>= 1.8.5) 43 | actionview (6.1.7.8) 44 | activesupport (= 6.1.7.8) 45 | builder (~> 3.1) 46 | erubi (~> 1.4) 47 | rails-dom-testing (~> 2.0) 48 | rails-html-sanitizer (~> 1.1, >= 1.2.0) 49 | activejob (6.1.7.8) 50 | activesupport (= 6.1.7.8) 51 | globalid (>= 0.3.6) 52 | activemodel (6.1.7.8) 53 | activesupport (= 6.1.7.8) 54 | activerecord (6.1.7.8) 55 | activemodel (= 6.1.7.8) 56 | activesupport (= 6.1.7.8) 57 | activestorage (6.1.7.8) 58 | actionpack (= 6.1.7.8) 59 | activejob (= 6.1.7.8) 60 | activerecord (= 6.1.7.8) 61 | activesupport (= 6.1.7.8) 62 | marcel (~> 1.0) 63 | mini_mime (>= 1.1.0) 64 | activesupport (6.1.7.8) 65 | concurrent-ruby (~> 1.0, >= 1.0.2) 66 | i18n (>= 1.6, < 2) 67 | minitest (>= 5.1) 68 | tzinfo (~> 2.0) 69 | zeitwerk (~> 2.3) 70 | appraisal (2.5.0) 71 | bundler 72 | rake 73 | thor (>= 0.14.0) 74 | ast (2.4.2) 75 | builder (3.3.0) 76 | concurrent-ruby (1.3.4) 77 | crass (1.0.6) 78 | date (3.3.4) 79 | erubi (1.13.0) 80 | globalid (1.2.1) 81 | activesupport (>= 6.1) 82 | i18n (1.14.5) 83 | concurrent-ruby (~> 1.0) 84 | json (2.7.2) 85 | language_server-protocol (3.17.0.3) 86 | lint_roller (1.1.0) 87 | loofah (2.22.0) 88 | crass (~> 1.0.2) 89 | nokogiri (>= 1.12.0) 90 | mail (2.8.1) 91 | mini_mime (>= 0.1.1) 92 | net-imap 93 | net-pop 94 | net-smtp 95 | marcel (1.0.4) 96 | method_source (1.1.0) 97 | mini_mime (1.1.5) 98 | minitest (5.25.1) 99 | net-imap (0.4.14) 100 | date 101 | net-protocol 102 | net-pop (0.1.2) 103 | net-protocol 104 | net-protocol (0.2.2) 105 | timeout 106 | net-smtp (0.5.0) 107 | net-protocol 108 | nio4r (2.7.3) 109 | nokogiri (1.16.7-aarch64-linux) 110 | racc (~> 1.4) 111 | nokogiri (1.16.7-arm-linux) 112 | racc (~> 1.4) 113 | nokogiri (1.16.7-arm64-darwin) 114 | racc (~> 1.4) 115 | nokogiri (1.16.7-x86-linux) 116 | racc (~> 1.4) 117 | nokogiri (1.16.7-x86_64-darwin) 118 | racc (~> 1.4) 119 | nokogiri (1.16.7-x86_64-linux) 120 | racc (~> 1.4) 121 | parallel (1.26.3) 122 | parser (3.3.4.2) 123 | ast (~> 2.4.1) 124 | racc 125 | puma (6.4.2) 126 | nio4r (~> 2.0) 127 | racc (1.8.1) 128 | rack (2.2.9) 129 | rack-test (2.1.0) 130 | rack (>= 1.3) 131 | rails (6.1.7.8) 132 | actioncable (= 6.1.7.8) 133 | actionmailbox (= 6.1.7.8) 134 | actionmailer (= 6.1.7.8) 135 | actionpack (= 6.1.7.8) 136 | actiontext (= 6.1.7.8) 137 | actionview (= 6.1.7.8) 138 | activejob (= 6.1.7.8) 139 | activemodel (= 6.1.7.8) 140 | activerecord (= 6.1.7.8) 141 | activestorage (= 6.1.7.8) 142 | activesupport (= 6.1.7.8) 143 | bundler (>= 1.15.0) 144 | railties (= 6.1.7.8) 145 | sprockets-rails (>= 2.0.0) 146 | rails-dom-testing (2.2.0) 147 | activesupport (>= 5.0.0) 148 | minitest 149 | nokogiri (>= 1.6) 150 | rails-html-sanitizer (1.6.0) 151 | loofah (~> 2.21) 152 | nokogiri (~> 1.14) 153 | railties (6.1.7.8) 154 | actionpack (= 6.1.7.8) 155 | activesupport (= 6.1.7.8) 156 | method_source 157 | rake (>= 12.2) 158 | thor (~> 1.0) 159 | rainbow (3.1.1) 160 | rake (13.2.1) 161 | regexp_parser (2.9.2) 162 | rexml (3.3.6) 163 | strscan 164 | rubocop (1.65.1) 165 | json (~> 2.3) 166 | language_server-protocol (>= 3.17.0) 167 | parallel (~> 1.10) 168 | parser (>= 3.3.0.2) 169 | rainbow (>= 2.2.2, < 4.0) 170 | regexp_parser (>= 2.4, < 3.0) 171 | rexml (>= 3.2.5, < 4.0) 172 | rubocop-ast (>= 1.31.1, < 2.0) 173 | ruby-progressbar (~> 1.7) 174 | unicode-display_width (>= 2.4.0, < 3.0) 175 | rubocop-ast (1.32.1) 176 | parser (>= 3.3.1.0) 177 | rubocop-performance (1.21.1) 178 | rubocop (>= 1.48.1, < 2.0) 179 | rubocop-ast (>= 1.31.1, < 2.0) 180 | rubocop-rails (2.25.1) 181 | activesupport (>= 4.2.0) 182 | rack (>= 1.1) 183 | rubocop (>= 1.33.0, < 2.0) 184 | rubocop-ast (>= 1.31.1, < 2.0) 185 | ruby-progressbar (1.13.0) 186 | sprockets (4.2.1) 187 | concurrent-ruby (~> 1.0) 188 | rack (>= 2.2.4, < 4) 189 | sprockets-rails (3.5.2) 190 | actionpack (>= 6.1) 191 | activesupport (>= 6.1) 192 | sprockets (>= 3.0.0) 193 | sqids (0.2.1) 194 | sqlite3 (1.7.3-aarch64-linux) 195 | sqlite3 (1.7.3-arm-linux) 196 | sqlite3 (1.7.3-arm64-darwin) 197 | sqlite3 (1.7.3-x86-linux) 198 | sqlite3 (1.7.3-x86_64-darwin) 199 | sqlite3 (1.7.3-x86_64-linux) 200 | standard (1.40.0) 201 | language_server-protocol (~> 3.17.0.2) 202 | lint_roller (~> 1.0) 203 | rubocop (~> 1.65.0) 204 | standard-custom (~> 1.0.0) 205 | standard-performance (~> 1.4) 206 | standard-custom (1.0.2) 207 | lint_roller (~> 1.0) 208 | rubocop (~> 1.50) 209 | standard-performance (1.4.0) 210 | lint_roller (~> 1.1) 211 | rubocop-performance (~> 1.21.0) 212 | standard-rails (1.1.0) 213 | lint_roller (~> 1.0) 214 | rubocop-rails (~> 2.25.0) 215 | strscan (3.1.0) 216 | thor (1.3.1) 217 | timeout (0.4.1) 218 | tzinfo (2.0.6) 219 | concurrent-ruby (~> 1.0) 220 | unicode-display_width (2.5.0) 221 | websocket-driver (0.7.6) 222 | websocket-extensions (>= 0.1.0) 223 | websocket-extensions (0.1.5) 224 | yard (0.9.36) 225 | zeitwerk (2.6.17) 226 | 227 | PLATFORMS 228 | aarch64-linux 229 | arm-linux 230 | arm64-darwin 231 | x86-linux 232 | x86_64-darwin 233 | x86_64-linux 234 | 235 | DEPENDENCIES 236 | appraisal 237 | puma 238 | rails (~> 6.1.0) 239 | sprockets-rails 240 | sqids-rails! 241 | sqlite3 (~> 1.7) 242 | standard (~> 1.39) 243 | standard-rails (~> 1.1) 244 | yard (~> 0.9.36) 245 | 246 | BUNDLED WITH 247 | 2.5.14 248 | -------------------------------------------------------------------------------- /gemfiles/rails_7_0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | sqids-rails (0.2.0) 5 | activerecord (>= 6.1.0) 6 | sqids (~> 0.2) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | actioncable (7.0.8.4) 12 | actionpack (= 7.0.8.4) 13 | activesupport (= 7.0.8.4) 14 | nio4r (~> 2.0) 15 | websocket-driver (>= 0.6.1) 16 | actionmailbox (7.0.8.4) 17 | actionpack (= 7.0.8.4) 18 | activejob (= 7.0.8.4) 19 | activerecord (= 7.0.8.4) 20 | activestorage (= 7.0.8.4) 21 | activesupport (= 7.0.8.4) 22 | mail (>= 2.7.1) 23 | net-imap 24 | net-pop 25 | net-smtp 26 | actionmailer (7.0.8.4) 27 | actionpack (= 7.0.8.4) 28 | actionview (= 7.0.8.4) 29 | activejob (= 7.0.8.4) 30 | activesupport (= 7.0.8.4) 31 | mail (~> 2.5, >= 2.5.4) 32 | net-imap 33 | net-pop 34 | net-smtp 35 | rails-dom-testing (~> 2.0) 36 | actionpack (7.0.8.4) 37 | actionview (= 7.0.8.4) 38 | activesupport (= 7.0.8.4) 39 | rack (~> 2.0, >= 2.2.4) 40 | rack-test (>= 0.6.3) 41 | rails-dom-testing (~> 2.0) 42 | rails-html-sanitizer (~> 1.0, >= 1.2.0) 43 | actiontext (7.0.8.4) 44 | actionpack (= 7.0.8.4) 45 | activerecord (= 7.0.8.4) 46 | activestorage (= 7.0.8.4) 47 | activesupport (= 7.0.8.4) 48 | globalid (>= 0.6.0) 49 | nokogiri (>= 1.8.5) 50 | actionview (7.0.8.4) 51 | activesupport (= 7.0.8.4) 52 | builder (~> 3.1) 53 | erubi (~> 1.4) 54 | rails-dom-testing (~> 2.0) 55 | rails-html-sanitizer (~> 1.1, >= 1.2.0) 56 | activejob (7.0.8.4) 57 | activesupport (= 7.0.8.4) 58 | globalid (>= 0.3.6) 59 | activemodel (7.0.8.4) 60 | activesupport (= 7.0.8.4) 61 | activerecord (7.0.8.4) 62 | activemodel (= 7.0.8.4) 63 | activesupport (= 7.0.8.4) 64 | activestorage (7.0.8.4) 65 | actionpack (= 7.0.8.4) 66 | activejob (= 7.0.8.4) 67 | activerecord (= 7.0.8.4) 68 | activesupport (= 7.0.8.4) 69 | marcel (~> 1.0) 70 | mini_mime (>= 1.1.0) 71 | activesupport (7.0.8.4) 72 | concurrent-ruby (~> 1.0, >= 1.0.2) 73 | i18n (>= 1.6, < 2) 74 | minitest (>= 5.1) 75 | tzinfo (~> 2.0) 76 | appraisal (2.5.0) 77 | bundler 78 | rake 79 | thor (>= 0.14.0) 80 | ast (2.4.2) 81 | builder (3.3.0) 82 | concurrent-ruby (1.3.4) 83 | crass (1.0.6) 84 | date (3.3.4) 85 | erubi (1.13.0) 86 | globalid (1.2.1) 87 | activesupport (>= 6.1) 88 | i18n (1.14.5) 89 | concurrent-ruby (~> 1.0) 90 | json (2.7.2) 91 | language_server-protocol (3.17.0.3) 92 | lint_roller (1.1.0) 93 | loofah (2.22.0) 94 | crass (~> 1.0.2) 95 | nokogiri (>= 1.12.0) 96 | mail (2.8.1) 97 | mini_mime (>= 0.1.1) 98 | net-imap 99 | net-pop 100 | net-smtp 101 | marcel (1.0.4) 102 | method_source (1.1.0) 103 | mini_mime (1.1.5) 104 | minitest (5.25.1) 105 | net-imap (0.4.14) 106 | date 107 | net-protocol 108 | net-pop (0.1.2) 109 | net-protocol 110 | net-protocol (0.2.2) 111 | timeout 112 | net-smtp (0.5.0) 113 | net-protocol 114 | nio4r (2.7.3) 115 | nokogiri (1.16.7-aarch64-linux) 116 | racc (~> 1.4) 117 | nokogiri (1.16.7-arm-linux) 118 | racc (~> 1.4) 119 | nokogiri (1.16.7-arm64-darwin) 120 | racc (~> 1.4) 121 | nokogiri (1.16.7-x86-linux) 122 | racc (~> 1.4) 123 | nokogiri (1.16.7-x86_64-darwin) 124 | racc (~> 1.4) 125 | nokogiri (1.16.7-x86_64-linux) 126 | racc (~> 1.4) 127 | parallel (1.26.3) 128 | parser (3.3.4.2) 129 | ast (~> 2.4.1) 130 | racc 131 | puma (6.4.2) 132 | nio4r (~> 2.0) 133 | racc (1.8.1) 134 | rack (2.2.9) 135 | rack-test (2.1.0) 136 | rack (>= 1.3) 137 | rails (7.0.8.4) 138 | actioncable (= 7.0.8.4) 139 | actionmailbox (= 7.0.8.4) 140 | actionmailer (= 7.0.8.4) 141 | actionpack (= 7.0.8.4) 142 | actiontext (= 7.0.8.4) 143 | actionview (= 7.0.8.4) 144 | activejob (= 7.0.8.4) 145 | activemodel (= 7.0.8.4) 146 | activerecord (= 7.0.8.4) 147 | activestorage (= 7.0.8.4) 148 | activesupport (= 7.0.8.4) 149 | bundler (>= 1.15.0) 150 | railties (= 7.0.8.4) 151 | rails-dom-testing (2.2.0) 152 | activesupport (>= 5.0.0) 153 | minitest 154 | nokogiri (>= 1.6) 155 | rails-html-sanitizer (1.6.0) 156 | loofah (~> 2.21) 157 | nokogiri (~> 1.14) 158 | railties (7.0.8.4) 159 | actionpack (= 7.0.8.4) 160 | activesupport (= 7.0.8.4) 161 | method_source 162 | rake (>= 12.2) 163 | thor (~> 1.0) 164 | zeitwerk (~> 2.5) 165 | rainbow (3.1.1) 166 | rake (13.2.1) 167 | regexp_parser (2.9.2) 168 | rexml (3.3.6) 169 | strscan 170 | rubocop (1.65.1) 171 | json (~> 2.3) 172 | language_server-protocol (>= 3.17.0) 173 | parallel (~> 1.10) 174 | parser (>= 3.3.0.2) 175 | rainbow (>= 2.2.2, < 4.0) 176 | regexp_parser (>= 2.4, < 3.0) 177 | rexml (>= 3.2.5, < 4.0) 178 | rubocop-ast (>= 1.31.1, < 2.0) 179 | ruby-progressbar (~> 1.7) 180 | unicode-display_width (>= 2.4.0, < 3.0) 181 | rubocop-ast (1.32.1) 182 | parser (>= 3.3.1.0) 183 | rubocop-performance (1.21.1) 184 | rubocop (>= 1.48.1, < 2.0) 185 | rubocop-ast (>= 1.31.1, < 2.0) 186 | rubocop-rails (2.25.1) 187 | activesupport (>= 4.2.0) 188 | rack (>= 1.1) 189 | rubocop (>= 1.33.0, < 2.0) 190 | rubocop-ast (>= 1.31.1, < 2.0) 191 | ruby-progressbar (1.13.0) 192 | sprockets (4.2.1) 193 | concurrent-ruby (~> 1.0) 194 | rack (>= 2.2.4, < 4) 195 | sprockets-rails (3.5.2) 196 | actionpack (>= 6.1) 197 | activesupport (>= 6.1) 198 | sprockets (>= 3.0.0) 199 | sqids (0.2.1) 200 | sqlite3 (1.7.3-aarch64-linux) 201 | sqlite3 (1.7.3-arm-linux) 202 | sqlite3 (1.7.3-arm64-darwin) 203 | sqlite3 (1.7.3-x86-linux) 204 | sqlite3 (1.7.3-x86_64-darwin) 205 | sqlite3 (1.7.3-x86_64-linux) 206 | standard (1.40.0) 207 | language_server-protocol (~> 3.17.0.2) 208 | lint_roller (~> 1.0) 209 | rubocop (~> 1.65.0) 210 | standard-custom (~> 1.0.0) 211 | standard-performance (~> 1.4) 212 | standard-custom (1.0.2) 213 | lint_roller (~> 1.0) 214 | rubocop (~> 1.50) 215 | standard-performance (1.4.0) 216 | lint_roller (~> 1.1) 217 | rubocop-performance (~> 1.21.0) 218 | standard-rails (1.1.0) 219 | lint_roller (~> 1.0) 220 | rubocop-rails (~> 2.25.0) 221 | strscan (3.1.0) 222 | thor (1.3.1) 223 | timeout (0.4.1) 224 | tzinfo (2.0.6) 225 | concurrent-ruby (~> 1.0) 226 | unicode-display_width (2.5.0) 227 | websocket-driver (0.7.6) 228 | websocket-extensions (>= 0.1.0) 229 | websocket-extensions (0.1.5) 230 | yard (0.9.36) 231 | zeitwerk (2.6.17) 232 | 233 | PLATFORMS 234 | aarch64-linux 235 | arm-linux 236 | arm64-darwin 237 | x86-linux 238 | x86_64-darwin 239 | x86_64-linux 240 | 241 | DEPENDENCIES 242 | appraisal 243 | puma 244 | rails (~> 7.0.0) 245 | sprockets-rails 246 | sqids-rails! 247 | sqlite3 (~> 1.7) 248 | standard (~> 1.39) 249 | standard-rails (~> 1.1) 250 | yard (~> 0.9.36) 251 | 252 | BUNDLED WITH 253 | 2.5.14 254 | -------------------------------------------------------------------------------- /gemfiles/rails_7_1.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | sqids-rails (0.2.0) 5 | activerecord (>= 6.1.0) 6 | sqids (~> 0.2) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | actioncable (7.1.4) 12 | actionpack (= 7.1.4) 13 | activesupport (= 7.1.4) 14 | nio4r (~> 2.0) 15 | websocket-driver (>= 0.6.1) 16 | zeitwerk (~> 2.6) 17 | actionmailbox (7.1.4) 18 | actionpack (= 7.1.4) 19 | activejob (= 7.1.4) 20 | activerecord (= 7.1.4) 21 | activestorage (= 7.1.4) 22 | activesupport (= 7.1.4) 23 | mail (>= 2.7.1) 24 | net-imap 25 | net-pop 26 | net-smtp 27 | actionmailer (7.1.4) 28 | actionpack (= 7.1.4) 29 | actionview (= 7.1.4) 30 | activejob (= 7.1.4) 31 | activesupport (= 7.1.4) 32 | mail (~> 2.5, >= 2.5.4) 33 | net-imap 34 | net-pop 35 | net-smtp 36 | rails-dom-testing (~> 2.2) 37 | actionpack (7.1.4) 38 | actionview (= 7.1.4) 39 | activesupport (= 7.1.4) 40 | nokogiri (>= 1.8.5) 41 | racc 42 | rack (>= 2.2.4) 43 | rack-session (>= 1.0.1) 44 | rack-test (>= 0.6.3) 45 | rails-dom-testing (~> 2.2) 46 | rails-html-sanitizer (~> 1.6) 47 | actiontext (7.1.4) 48 | actionpack (= 7.1.4) 49 | activerecord (= 7.1.4) 50 | activestorage (= 7.1.4) 51 | activesupport (= 7.1.4) 52 | globalid (>= 0.6.0) 53 | nokogiri (>= 1.8.5) 54 | actionview (7.1.4) 55 | activesupport (= 7.1.4) 56 | builder (~> 3.1) 57 | erubi (~> 1.11) 58 | rails-dom-testing (~> 2.2) 59 | rails-html-sanitizer (~> 1.6) 60 | activejob (7.1.4) 61 | activesupport (= 7.1.4) 62 | globalid (>= 0.3.6) 63 | activemodel (7.1.4) 64 | activesupport (= 7.1.4) 65 | activerecord (7.1.4) 66 | activemodel (= 7.1.4) 67 | activesupport (= 7.1.4) 68 | timeout (>= 0.4.0) 69 | activestorage (7.1.4) 70 | actionpack (= 7.1.4) 71 | activejob (= 7.1.4) 72 | activerecord (= 7.1.4) 73 | activesupport (= 7.1.4) 74 | marcel (~> 1.0) 75 | activesupport (7.1.4) 76 | base64 77 | bigdecimal 78 | concurrent-ruby (~> 1.0, >= 1.0.2) 79 | connection_pool (>= 2.2.5) 80 | drb 81 | i18n (>= 1.6, < 2) 82 | minitest (>= 5.1) 83 | mutex_m 84 | tzinfo (~> 2.0) 85 | appraisal (2.5.0) 86 | bundler 87 | rake 88 | thor (>= 0.14.0) 89 | ast (2.4.2) 90 | base64 (0.2.0) 91 | bigdecimal (3.1.8) 92 | builder (3.3.0) 93 | concurrent-ruby (1.3.4) 94 | connection_pool (2.4.1) 95 | crass (1.0.6) 96 | date (3.3.4) 97 | drb (2.2.1) 98 | erubi (1.13.0) 99 | globalid (1.2.1) 100 | activesupport (>= 6.1) 101 | i18n (1.14.5) 102 | concurrent-ruby (~> 1.0) 103 | io-console (0.7.2) 104 | irb (1.14.0) 105 | rdoc (>= 4.0.0) 106 | reline (>= 0.4.2) 107 | json (2.7.2) 108 | language_server-protocol (3.17.0.3) 109 | lint_roller (1.1.0) 110 | loofah (2.22.0) 111 | crass (~> 1.0.2) 112 | nokogiri (>= 1.12.0) 113 | mail (2.8.1) 114 | mini_mime (>= 0.1.1) 115 | net-imap 116 | net-pop 117 | net-smtp 118 | marcel (1.0.4) 119 | mini_mime (1.1.5) 120 | minitest (5.25.1) 121 | mutex_m (0.2.0) 122 | net-imap (0.4.14) 123 | date 124 | net-protocol 125 | net-pop (0.1.2) 126 | net-protocol 127 | net-protocol (0.2.2) 128 | timeout 129 | net-smtp (0.5.0) 130 | net-protocol 131 | nio4r (2.7.3) 132 | nokogiri (1.16.7-arm64-darwin) 133 | racc (~> 1.4) 134 | parallel (1.26.3) 135 | parser (3.3.4.2) 136 | ast (~> 2.4.1) 137 | racc 138 | psych (5.1.2) 139 | stringio 140 | puma (6.4.2) 141 | nio4r (~> 2.0) 142 | racc (1.8.1) 143 | rack (3.1.7) 144 | rack-session (2.0.0) 145 | rack (>= 3.0.0) 146 | rack-test (2.1.0) 147 | rack (>= 1.3) 148 | rackup (2.1.0) 149 | rack (>= 3) 150 | webrick (~> 1.8) 151 | rails (7.1.4) 152 | actioncable (= 7.1.4) 153 | actionmailbox (= 7.1.4) 154 | actionmailer (= 7.1.4) 155 | actionpack (= 7.1.4) 156 | actiontext (= 7.1.4) 157 | actionview (= 7.1.4) 158 | activejob (= 7.1.4) 159 | activemodel (= 7.1.4) 160 | activerecord (= 7.1.4) 161 | activestorage (= 7.1.4) 162 | activesupport (= 7.1.4) 163 | bundler (>= 1.15.0) 164 | railties (= 7.1.4) 165 | rails-dom-testing (2.2.0) 166 | activesupport (>= 5.0.0) 167 | minitest 168 | nokogiri (>= 1.6) 169 | rails-html-sanitizer (1.6.0) 170 | loofah (~> 2.21) 171 | nokogiri (~> 1.14) 172 | railties (7.1.4) 173 | actionpack (= 7.1.4) 174 | activesupport (= 7.1.4) 175 | irb 176 | rackup (>= 1.0.0) 177 | rake (>= 12.2) 178 | thor (~> 1.0, >= 1.2.2) 179 | zeitwerk (~> 2.6) 180 | rainbow (3.1.1) 181 | rake (13.2.1) 182 | rdoc (6.7.0) 183 | psych (>= 4.0.0) 184 | regexp_parser (2.9.2) 185 | reline (0.5.9) 186 | io-console (~> 0.5) 187 | rexml (3.3.6) 188 | strscan 189 | rubocop (1.65.1) 190 | json (~> 2.3) 191 | language_server-protocol (>= 3.17.0) 192 | parallel (~> 1.10) 193 | parser (>= 3.3.0.2) 194 | rainbow (>= 2.2.2, < 4.0) 195 | regexp_parser (>= 2.4, < 3.0) 196 | rexml (>= 3.2.5, < 4.0) 197 | rubocop-ast (>= 1.31.1, < 2.0) 198 | ruby-progressbar (~> 1.7) 199 | unicode-display_width (>= 2.4.0, < 3.0) 200 | rubocop-ast (1.32.1) 201 | parser (>= 3.3.1.0) 202 | rubocop-performance (1.21.1) 203 | rubocop (>= 1.48.1, < 2.0) 204 | rubocop-ast (>= 1.31.1, < 2.0) 205 | rubocop-rails (2.25.1) 206 | activesupport (>= 4.2.0) 207 | rack (>= 1.1) 208 | rubocop (>= 1.33.0, < 2.0) 209 | rubocop-ast (>= 1.31.1, < 2.0) 210 | ruby-progressbar (1.13.0) 211 | sprockets (4.2.1) 212 | concurrent-ruby (~> 1.0) 213 | rack (>= 2.2.4, < 4) 214 | sprockets-rails (3.5.2) 215 | actionpack (>= 6.1) 216 | activesupport (>= 6.1) 217 | sprockets (>= 3.0.0) 218 | sqids (0.2.1) 219 | sqlite3 (1.7.3-arm64-darwin) 220 | standard (1.40.0) 221 | language_server-protocol (~> 3.17.0.2) 222 | lint_roller (~> 1.0) 223 | rubocop (~> 1.65.0) 224 | standard-custom (~> 1.0.0) 225 | standard-performance (~> 1.4) 226 | standard-custom (1.0.2) 227 | lint_roller (~> 1.0) 228 | rubocop (~> 1.50) 229 | standard-performance (1.4.0) 230 | lint_roller (~> 1.1) 231 | rubocop-performance (~> 1.21.0) 232 | standard-rails (1.1.0) 233 | lint_roller (~> 1.0) 234 | rubocop-rails (~> 2.25.0) 235 | stringio (3.1.1) 236 | strscan (3.1.0) 237 | thor (1.3.1) 238 | timeout (0.4.1) 239 | tzinfo (2.0.6) 240 | concurrent-ruby (~> 1.0) 241 | unicode-display_width (2.5.0) 242 | webrick (1.8.1) 243 | websocket-driver (0.7.6) 244 | websocket-extensions (>= 0.1.0) 245 | websocket-extensions (0.1.5) 246 | yard (0.9.36) 247 | zeitwerk (2.6.17) 248 | 249 | PLATFORMS 250 | arm64-darwin 251 | 252 | DEPENDENCIES 253 | appraisal 254 | puma 255 | rails (~> 7.1.0) 256 | sprockets-rails 257 | sqids-rails! 258 | sqlite3 (~> 1.7) 259 | standard (~> 1.39) 260 | standard-rails (~> 1.1) 261 | yard (~> 0.9.36) 262 | 263 | BUNDLED WITH 264 | 2.5.14 265 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | sqids-rails (0.2.0) 5 | activerecord (>= 6.1.0) 6 | sqids (~> 0.2) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | actioncable (7.2.1) 12 | actionpack (= 7.2.1) 13 | activesupport (= 7.2.1) 14 | nio4r (~> 2.0) 15 | websocket-driver (>= 0.6.1) 16 | zeitwerk (~> 2.6) 17 | actionmailbox (7.2.1) 18 | actionpack (= 7.2.1) 19 | activejob (= 7.2.1) 20 | activerecord (= 7.2.1) 21 | activestorage (= 7.2.1) 22 | activesupport (= 7.2.1) 23 | mail (>= 2.8.0) 24 | actionmailer (7.2.1) 25 | actionpack (= 7.2.1) 26 | actionview (= 7.2.1) 27 | activejob (= 7.2.1) 28 | activesupport (= 7.2.1) 29 | mail (>= 2.8.0) 30 | rails-dom-testing (~> 2.2) 31 | actionpack (7.2.1) 32 | actionview (= 7.2.1) 33 | activesupport (= 7.2.1) 34 | nokogiri (>= 1.8.5) 35 | racc 36 | rack (>= 2.2.4, < 3.2) 37 | rack-session (>= 1.0.1) 38 | rack-test (>= 0.6.3) 39 | rails-dom-testing (~> 2.2) 40 | rails-html-sanitizer (~> 1.6) 41 | useragent (~> 0.16) 42 | actiontext (7.2.1) 43 | actionpack (= 7.2.1) 44 | activerecord (= 7.2.1) 45 | activestorage (= 7.2.1) 46 | activesupport (= 7.2.1) 47 | globalid (>= 0.6.0) 48 | nokogiri (>= 1.8.5) 49 | actionview (7.2.1) 50 | activesupport (= 7.2.1) 51 | builder (~> 3.1) 52 | erubi (~> 1.11) 53 | rails-dom-testing (~> 2.2) 54 | rails-html-sanitizer (~> 1.6) 55 | activejob (7.2.1) 56 | activesupport (= 7.2.1) 57 | globalid (>= 0.3.6) 58 | activemodel (7.2.1) 59 | activesupport (= 7.2.1) 60 | activerecord (7.2.1) 61 | activemodel (= 7.2.1) 62 | activesupport (= 7.2.1) 63 | timeout (>= 0.4.0) 64 | activestorage (7.2.1) 65 | actionpack (= 7.2.1) 66 | activejob (= 7.2.1) 67 | activerecord (= 7.2.1) 68 | activesupport (= 7.2.1) 69 | marcel (~> 1.0) 70 | activesupport (7.2.1) 71 | base64 72 | bigdecimal 73 | concurrent-ruby (~> 1.0, >= 1.3.1) 74 | connection_pool (>= 2.2.5) 75 | drb 76 | i18n (>= 1.6, < 2) 77 | logger (>= 1.4.2) 78 | minitest (>= 5.1) 79 | securerandom (>= 0.3) 80 | tzinfo (~> 2.0, >= 2.0.5) 81 | appraisal (2.5.0) 82 | bundler 83 | rake 84 | thor (>= 0.14.0) 85 | ast (2.4.2) 86 | base64 (0.2.0) 87 | bigdecimal (3.1.8) 88 | builder (3.3.0) 89 | concurrent-ruby (1.3.4) 90 | connection_pool (2.4.1) 91 | crass (1.0.6) 92 | date (3.3.4) 93 | drb (2.2.1) 94 | erubi (1.13.0) 95 | globalid (1.2.1) 96 | activesupport (>= 6.1) 97 | i18n (1.14.5) 98 | concurrent-ruby (~> 1.0) 99 | io-console (0.7.2) 100 | irb (1.14.0) 101 | rdoc (>= 4.0.0) 102 | reline (>= 0.4.2) 103 | json (2.7.2) 104 | language_server-protocol (3.17.0.3) 105 | lint_roller (1.1.0) 106 | logger (1.6.0) 107 | loofah (2.22.0) 108 | crass (~> 1.0.2) 109 | nokogiri (>= 1.12.0) 110 | mail (2.8.1) 111 | mini_mime (>= 0.1.1) 112 | net-imap 113 | net-pop 114 | net-smtp 115 | marcel (1.0.4) 116 | mini_mime (1.1.5) 117 | minitest (5.25.1) 118 | net-imap (0.4.14) 119 | date 120 | net-protocol 121 | net-pop (0.1.2) 122 | net-protocol 123 | net-protocol (0.2.2) 124 | timeout 125 | net-smtp (0.5.0) 126 | net-protocol 127 | nio4r (2.7.3) 128 | nokogiri (1.16.7-aarch64-linux) 129 | racc (~> 1.4) 130 | nokogiri (1.16.7-arm-linux) 131 | racc (~> 1.4) 132 | nokogiri (1.16.7-arm64-darwin) 133 | racc (~> 1.4) 134 | nokogiri (1.16.7-x86-linux) 135 | racc (~> 1.4) 136 | nokogiri (1.16.7-x86_64-darwin) 137 | racc (~> 1.4) 138 | nokogiri (1.16.7-x86_64-linux) 139 | racc (~> 1.4) 140 | parallel (1.26.3) 141 | parser (3.3.4.2) 142 | ast (~> 2.4.1) 143 | racc 144 | psych (5.1.2) 145 | stringio 146 | puma (6.4.2) 147 | nio4r (~> 2.0) 148 | racc (1.8.1) 149 | rack (3.1.7) 150 | rack-session (2.0.0) 151 | rack (>= 3.0.0) 152 | rack-test (2.1.0) 153 | rack (>= 1.3) 154 | rackup (2.1.0) 155 | rack (>= 3) 156 | webrick (~> 1.8) 157 | rails (7.2.1) 158 | actioncable (= 7.2.1) 159 | actionmailbox (= 7.2.1) 160 | actionmailer (= 7.2.1) 161 | actionpack (= 7.2.1) 162 | actiontext (= 7.2.1) 163 | actionview (= 7.2.1) 164 | activejob (= 7.2.1) 165 | activemodel (= 7.2.1) 166 | activerecord (= 7.2.1) 167 | activestorage (= 7.2.1) 168 | activesupport (= 7.2.1) 169 | bundler (>= 1.15.0) 170 | railties (= 7.2.1) 171 | rails-dom-testing (2.2.0) 172 | activesupport (>= 5.0.0) 173 | minitest 174 | nokogiri (>= 1.6) 175 | rails-html-sanitizer (1.6.0) 176 | loofah (~> 2.21) 177 | nokogiri (~> 1.14) 178 | railties (7.2.1) 179 | actionpack (= 7.2.1) 180 | activesupport (= 7.2.1) 181 | irb (~> 1.13) 182 | rackup (>= 1.0.0) 183 | rake (>= 12.2) 184 | thor (~> 1.0, >= 1.2.2) 185 | zeitwerk (~> 2.6) 186 | rainbow (3.1.1) 187 | rake (13.2.1) 188 | rdoc (6.7.0) 189 | psych (>= 4.0.0) 190 | regexp_parser (2.9.2) 191 | reline (0.5.9) 192 | io-console (~> 0.5) 193 | rexml (3.3.6) 194 | strscan 195 | rubocop (1.65.1) 196 | json (~> 2.3) 197 | language_server-protocol (>= 3.17.0) 198 | parallel (~> 1.10) 199 | parser (>= 3.3.0.2) 200 | rainbow (>= 2.2.2, < 4.0) 201 | regexp_parser (>= 2.4, < 3.0) 202 | rexml (>= 3.2.5, < 4.0) 203 | rubocop-ast (>= 1.31.1, < 2.0) 204 | ruby-progressbar (~> 1.7) 205 | unicode-display_width (>= 2.4.0, < 3.0) 206 | rubocop-ast (1.32.1) 207 | parser (>= 3.3.1.0) 208 | rubocop-performance (1.21.1) 209 | rubocop (>= 1.48.1, < 2.0) 210 | rubocop-ast (>= 1.31.1, < 2.0) 211 | rubocop-rails (2.26.0) 212 | activesupport (>= 4.2.0) 213 | rack (>= 1.1) 214 | rubocop (>= 1.52.0, < 2.0) 215 | rubocop-ast (>= 1.31.1, < 2.0) 216 | ruby-progressbar (1.13.0) 217 | securerandom (0.3.1) 218 | sprockets (4.2.1) 219 | concurrent-ruby (~> 1.0) 220 | rack (>= 2.2.4, < 4) 221 | sprockets-rails (3.5.2) 222 | actionpack (>= 6.1) 223 | activesupport (>= 6.1) 224 | sprockets (>= 3.0.0) 225 | sqids (0.2.1) 226 | sqlite3 (1.7.3-aarch64-linux) 227 | sqlite3 (1.7.3-arm-linux) 228 | sqlite3 (1.7.3-arm64-darwin) 229 | sqlite3 (1.7.3-x86-linux) 230 | sqlite3 (1.7.3-x86_64-darwin) 231 | sqlite3 (1.7.3-x86_64-linux) 232 | standard (1.40.0) 233 | language_server-protocol (~> 3.17.0.2) 234 | lint_roller (~> 1.0) 235 | rubocop (~> 1.65.0) 236 | standard-custom (~> 1.0.0) 237 | standard-performance (~> 1.4) 238 | standard-custom (1.0.2) 239 | lint_roller (~> 1.0) 240 | rubocop (~> 1.50) 241 | standard-performance (1.4.0) 242 | lint_roller (~> 1.1) 243 | rubocop-performance (~> 1.21.0) 244 | standard-rails (1.2.0) 245 | lint_roller (~> 1.0) 246 | rubocop-rails (~> 2.26.0) 247 | stringio (3.1.1) 248 | strscan (3.1.0) 249 | thor (1.3.1) 250 | timeout (0.4.1) 251 | tzinfo (2.0.6) 252 | concurrent-ruby (~> 1.0) 253 | unicode-display_width (2.5.0) 254 | useragent (0.16.10) 255 | webrick (1.8.1) 256 | websocket-driver (0.7.6) 257 | websocket-extensions (>= 0.1.0) 258 | websocket-extensions (0.1.5) 259 | yard (0.9.37) 260 | zeitwerk (2.6.17) 261 | 262 | PLATFORMS 263 | aarch64-linux 264 | aarch64-linux-gnu 265 | aarch64-linux-musl 266 | arm-linux 267 | arm-linux-gnu 268 | arm-linux-musl 269 | arm64-darwin 270 | x86-linux 271 | x86-linux-gnu 272 | x86-linux-musl 273 | x86_64-darwin 274 | x86_64-linux 275 | x86_64-linux-gnu 276 | x86_64-linux-musl 277 | 278 | DEPENDENCIES 279 | appraisal 280 | puma 281 | rails (~> 7.2.0) 282 | sprockets-rails 283 | sqids-rails! 284 | sqlite3 (~> 1.7) 285 | standard (~> 1.39) 286 | standard-rails (~> 1.2) 287 | yard (~> 0.9.37) 288 | 289 | BUNDLED WITH 290 | 2.5.14 291 | -------------------------------------------------------------------------------- /gemfiles/rails_7_2.gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: https://github.com/ruby/net-pop.git 3 | revision: e8d0afe2773b9eb6a23c39e9e437f6fc0fc7c733 4 | specs: 5 | net-pop (0.1.2) 6 | net-protocol 7 | 8 | PATH 9 | remote: .. 10 | specs: 11 | sqids-rails (0.1.1) 12 | activerecord (>= 6.1.0) 13 | sqids (~> 0.2) 14 | 15 | GEM 16 | remote: https://rubygems.org/ 17 | specs: 18 | actioncable (7.2.0.beta2) 19 | actionpack (= 7.2.0.beta2) 20 | activesupport (= 7.2.0.beta2) 21 | nio4r (~> 2.0) 22 | websocket-driver (>= 0.6.1) 23 | zeitwerk (~> 2.6) 24 | actionmailbox (7.2.0.beta2) 25 | actionpack (= 7.2.0.beta2) 26 | activejob (= 7.2.0.beta2) 27 | activerecord (= 7.2.0.beta2) 28 | activestorage (= 7.2.0.beta2) 29 | activesupport (= 7.2.0.beta2) 30 | mail (>= 2.8.0) 31 | actionmailer (7.2.0.beta2) 32 | actionpack (= 7.2.0.beta2) 33 | actionview (= 7.2.0.beta2) 34 | activejob (= 7.2.0.beta2) 35 | activesupport (= 7.2.0.beta2) 36 | mail (>= 2.8.0) 37 | rails-dom-testing (~> 2.2) 38 | actionpack (7.2.0.beta2) 39 | actionview (= 7.2.0.beta2) 40 | activesupport (= 7.2.0.beta2) 41 | nokogiri (>= 1.8.5) 42 | racc 43 | rack (>= 2.2.4) 44 | rack-session (>= 1.0.1) 45 | rack-test (>= 0.6.3) 46 | rails-dom-testing (~> 2.2) 47 | rails-html-sanitizer (~> 1.6) 48 | useragent (~> 0.16) 49 | actiontext (7.2.0.beta2) 50 | actionpack (= 7.2.0.beta2) 51 | activerecord (= 7.2.0.beta2) 52 | activestorage (= 7.2.0.beta2) 53 | activesupport (= 7.2.0.beta2) 54 | globalid (>= 0.6.0) 55 | nokogiri (>= 1.8.5) 56 | actionview (7.2.0.beta2) 57 | activesupport (= 7.2.0.beta2) 58 | builder (~> 3.1) 59 | erubi (~> 1.11) 60 | rails-dom-testing (~> 2.2) 61 | rails-html-sanitizer (~> 1.6) 62 | activejob (7.2.0.beta2) 63 | activesupport (= 7.2.0.beta2) 64 | globalid (>= 0.3.6) 65 | activemodel (7.2.0.beta2) 66 | activesupport (= 7.2.0.beta2) 67 | activerecord (7.2.0.beta2) 68 | activemodel (= 7.2.0.beta2) 69 | activesupport (= 7.2.0.beta2) 70 | timeout (>= 0.4.0) 71 | activestorage (7.2.0.beta2) 72 | actionpack (= 7.2.0.beta2) 73 | activejob (= 7.2.0.beta2) 74 | activerecord (= 7.2.0.beta2) 75 | activesupport (= 7.2.0.beta2) 76 | marcel (~> 1.0) 77 | activesupport (7.2.0.beta2) 78 | base64 79 | bigdecimal 80 | concurrent-ruby (~> 1.0, >= 1.3.1) 81 | connection_pool (>= 2.2.5) 82 | drb 83 | i18n (>= 1.6, < 2) 84 | minitest (>= 5.1) 85 | tzinfo (~> 2.0, >= 2.0.5) 86 | appraisal (2.5.0) 87 | bundler 88 | rake 89 | thor (>= 0.14.0) 90 | ast (2.4.2) 91 | base64 (0.2.0) 92 | bigdecimal (3.1.8) 93 | builder (3.3.0) 94 | concurrent-ruby (1.3.3) 95 | connection_pool (2.4.1) 96 | crass (1.0.6) 97 | date (3.3.4) 98 | drb (2.2.1) 99 | erubi (1.13.0) 100 | globalid (1.2.1) 101 | activesupport (>= 6.1) 102 | i18n (1.14.5) 103 | concurrent-ruby (~> 1.0) 104 | io-console (0.7.2) 105 | irb (1.13.2) 106 | rdoc (>= 4.0.0) 107 | reline (>= 0.4.2) 108 | json (2.7.2) 109 | language_server-protocol (3.17.0.3) 110 | lint_roller (1.1.0) 111 | loofah (2.22.0) 112 | crass (~> 1.0.2) 113 | nokogiri (>= 1.12.0) 114 | mail (2.8.1) 115 | mini_mime (>= 0.1.1) 116 | net-imap 117 | net-pop 118 | net-smtp 119 | marcel (1.0.4) 120 | mini_mime (1.1.5) 121 | minitest (5.24.1) 122 | net-imap (0.4.14) 123 | date 124 | net-protocol 125 | net-protocol (0.2.2) 126 | timeout 127 | net-smtp (0.5.0) 128 | net-protocol 129 | nio4r (2.7.3) 130 | nokogiri (1.16.6-aarch64-linux) 131 | racc (~> 1.4) 132 | nokogiri (1.16.6-arm-linux) 133 | racc (~> 1.4) 134 | nokogiri (1.16.6-arm64-darwin) 135 | racc (~> 1.4) 136 | nokogiri (1.16.6-x86-linux) 137 | racc (~> 1.4) 138 | nokogiri (1.16.6-x86_64-darwin) 139 | racc (~> 1.4) 140 | nokogiri (1.16.6-x86_64-linux) 141 | racc (~> 1.4) 142 | parallel (1.25.1) 143 | parser (3.3.3.0) 144 | ast (~> 2.4.1) 145 | racc 146 | psych (5.1.2) 147 | stringio 148 | puma (6.4.2) 149 | nio4r (~> 2.0) 150 | racc (1.8.0) 151 | rack (3.1.6) 152 | rack-session (2.0.0) 153 | rack (>= 3.0.0) 154 | rack-test (2.1.0) 155 | rack (>= 1.3) 156 | rackup (2.1.0) 157 | rack (>= 3) 158 | webrick (~> 1.8) 159 | rails (7.2.0.beta2) 160 | actioncable (= 7.2.0.beta2) 161 | actionmailbox (= 7.2.0.beta2) 162 | actionmailer (= 7.2.0.beta2) 163 | actionpack (= 7.2.0.beta2) 164 | actiontext (= 7.2.0.beta2) 165 | actionview (= 7.2.0.beta2) 166 | activejob (= 7.2.0.beta2) 167 | activemodel (= 7.2.0.beta2) 168 | activerecord (= 7.2.0.beta2) 169 | activestorage (= 7.2.0.beta2) 170 | activesupport (= 7.2.0.beta2) 171 | bundler (>= 1.15.0) 172 | railties (= 7.2.0.beta2) 173 | rails-dom-testing (2.2.0) 174 | activesupport (>= 5.0.0) 175 | minitest 176 | nokogiri (>= 1.6) 177 | rails-html-sanitizer (1.6.0) 178 | loofah (~> 2.21) 179 | nokogiri (~> 1.14) 180 | railties (7.2.0.beta2) 181 | actionpack (= 7.2.0.beta2) 182 | activesupport (= 7.2.0.beta2) 183 | irb (~> 1.13) 184 | rackup (>= 1.0.0) 185 | rake (>= 12.2) 186 | thor (~> 1.0, >= 1.2.2) 187 | zeitwerk (~> 2.6) 188 | rainbow (3.1.1) 189 | rake (13.2.1) 190 | rdoc (6.7.0) 191 | psych (>= 4.0.0) 192 | regexp_parser (2.9.2) 193 | reline (0.5.9) 194 | io-console (~> 0.5) 195 | rexml (3.3.1) 196 | strscan 197 | rubocop (1.64.1) 198 | json (~> 2.3) 199 | language_server-protocol (>= 3.17.0) 200 | parallel (~> 1.10) 201 | parser (>= 3.3.0.2) 202 | rainbow (>= 2.2.2, < 4.0) 203 | regexp_parser (>= 1.8, < 3.0) 204 | rexml (>= 3.2.5, < 4.0) 205 | rubocop-ast (>= 1.31.1, < 2.0) 206 | ruby-progressbar (~> 1.7) 207 | unicode-display_width (>= 2.4.0, < 3.0) 208 | rubocop-ast (1.31.3) 209 | parser (>= 3.3.1.0) 210 | rubocop-performance (1.21.1) 211 | rubocop (>= 1.48.1, < 2.0) 212 | rubocop-ast (>= 1.31.1, < 2.0) 213 | rubocop-rails (2.25.1) 214 | activesupport (>= 4.2.0) 215 | rack (>= 1.1) 216 | rubocop (>= 1.33.0, < 2.0) 217 | rubocop-ast (>= 1.31.1, < 2.0) 218 | ruby-progressbar (1.13.0) 219 | sprockets (4.2.1) 220 | concurrent-ruby (~> 1.0) 221 | rack (>= 2.2.4, < 4) 222 | sprockets-rails (3.5.1) 223 | actionpack (>= 6.1) 224 | activesupport (>= 6.1) 225 | sprockets (>= 3.0.0) 226 | sqids (0.2.0) 227 | sqlite3 (1.7.3-aarch64-linux) 228 | sqlite3 (1.7.3-arm-linux) 229 | sqlite3 (1.7.3-arm64-darwin) 230 | sqlite3 (1.7.3-x86-linux) 231 | sqlite3 (1.7.3-x86_64-darwin) 232 | sqlite3 (1.7.3-x86_64-linux) 233 | standard (1.39.1) 234 | language_server-protocol (~> 3.17.0.2) 235 | lint_roller (~> 1.0) 236 | rubocop (~> 1.64.0) 237 | standard-custom (~> 1.0.0) 238 | standard-performance (~> 1.4) 239 | standard-custom (1.0.2) 240 | lint_roller (~> 1.0) 241 | rubocop (~> 1.50) 242 | standard-performance (1.4.0) 243 | lint_roller (~> 1.1) 244 | rubocop-performance (~> 1.21.0) 245 | standard-rails (1.1.0) 246 | lint_roller (~> 1.0) 247 | rubocop-rails (~> 2.25.0) 248 | stringio (3.1.1) 249 | strscan (3.1.0) 250 | thor (1.3.1) 251 | timeout (0.4.1) 252 | tzinfo (2.0.6) 253 | concurrent-ruby (~> 1.0) 254 | unicode-display_width (2.5.0) 255 | useragent (0.16.10) 256 | webrick (1.8.1) 257 | websocket-driver (0.7.6) 258 | websocket-extensions (>= 0.1.0) 259 | websocket-extensions (0.1.5) 260 | yard (0.9.36) 261 | zeitwerk (2.6.16) 262 | 263 | PLATFORMS 264 | aarch64-linux 265 | arm-linux 266 | arm64-darwin 267 | x86-linux 268 | x86_64-darwin 269 | x86_64-linux 270 | 271 | DEPENDENCIES 272 | appraisal 273 | net-pop! 274 | puma 275 | rails (~> 7.2.0.beta2) 276 | sprockets-rails 277 | sqids-rails! 278 | sqlite3 (~> 1.7) 279 | standard (~> 1.39) 280 | standard-rails (~> 1.1) 281 | yard (~> 0.9.36) 282 | 283 | BUNDLED WITH 284 | 2.5.14 285 | --------------------------------------------------------------------------------