Install the prefixed_ids gem
mainAdd prefixed_ids to your application's Gemfile to enable friendly, prefixed ID generation for your Ruby on Rails models.
gem 'prefixed_ids'repository·main·Indexed 19 days ago
https://github.com/excid3/prefixed_idsA Ruby on Rails gem that generates human-friendly, prefixed IDs by hashing a record's primary key using Hashids. It integrates with Rails' find and to_param methods, providing tools to encode/decode IDs, secure them with global or per-model salts, and look up records across registered models using PrefixedIds.find.
Add prefixed_ids to your application's Gemfile to enable friendly, prefixed ID generation for your Ruby on Rails models.
gem 'prefixed_ids'To prevent users from reverse-engineering your IDs, you should use a salt. This makes the hashed values unguessable.
You can define a Global Salt in an initializer or a Per Model Salt directly in the model declaration.
# Global Salt
# config/initializers/prefixed_ids.rb
PrefixedIds.salt = "salt"
# Per Model Salt
class User < ApplicationRecord
has_prefix_id :user, salt: "usersalt"
endWhen using has_prefix_id, the library extends associations to support prefixed IDs:
belongs_to associations:
If the associated model uses has_prefix_id, a helper method #{association_name}_prefix_id is generated. This allows you to get or set the association using the prefixed string instead of the foreign key integer.
has_many associations:
relation is extended with prefix_ids, allowing you to call association.prefix_ids to get prefixed strings for all members of the collection.has_many method is extended to include ClassMethods (like find_by_prefix_id) on the association proxy.class Post < ApplicationRecord
belongs_to :user
end
post = Post.first
post.user_prefix_id # => "user_abc123"
post.user_prefix_id = "user_xyz789" # Sets the foreign key via decodingTo use friendly prefixed IDs in a Ruby on Rails model, include the has_prefix_id macro in your class. This enables encoding the model's ID into a prefixed string (e.g., user_abc123) and provides several helper methods for finding and decoding these IDs.
By default, has_prefix_id enables:
find to support prefixed IDs and adds find_by_prefix_id.to_param so that model.to_param returns the prefixed ID.You can disable these features using the following options:
override_find: falseoverride_param: falsefallback: false (disables fallback decoding if the ID is invalid)class User < ApplicationRecord
has_prefix_id :user
endThe PrefixedIds::Engine automatically integrates the library with Rails. It uses a Rails initializer to hook into ActiveRecord. When ActiveRecord is loaded, the PrefixedIds::Rails module is included, which provides the necessary functionality for using prefixed IDs within your Rails models.
# The engine automatically performs the following when the gem is loaded in a Rails app:
ActiveSupport.on_load(:active_record) do
include PrefixedIds::Rails
endThe gem provides several ways to find records using their prefixed ID string:
find override: By default, Model.find("prefix_id") works seamlessly. Note that find still supports regular primary keys (e.g., User.find(1) still works).override_find: false in your model configuration, use:Model.find_by_prefix_id("prefix_id"): Returns the record or nil.Model.find_by_prefix_id!("prefix_id"): Raises an exception if the record is not found.To disable the automatic find and to_param overrides, use the following configuration:
class User < ApplicationRecord
has_prefix_id :user, override_find: false, override_param: false
endIf you have a prefixed ID but do not know which model it belongs to, you can use PrefixedIds.find. This behaves similarly to Rails' GlobalID.
PrefixedIds.find("user_5vJjbzXq9KrLEMm3")
#=> #<User>
PrefixedIds.find("acct_2iAnOP0xGDYk6dpe")
#=> #<Account>To autogenerate prefixed IDs, add has_prefix_id :prefix to your model.
Important: You must place has_prefix_id before your associations, as it overrides has_many to include prefix ID helpers.
By default, this overrides to_param so that @model.to_param returns the prefixed string (e.g., user_12345abcd).
class User < ApplicationRecord
has_prefix_id :user
endYou can customize the encoding behavior globally via PrefixedIds configuration. These settings affect how Hashids generates the encoded portion of the ID.
Available configuration keys:
delimiter: The character used to separate the prefix from the encoded ID (default: _).alphabet: The characters used for encoding (default: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890).minimum_length: The minimum length of the encoded ID portion (default: 24).salt: The salt used for Hashids (default: "").PrefixedIds.delimiter = "-"
PrefixedIds.salt = "my_secret_salt"
PrefixedIds.minimum_length = 16You can fine-tune how prefixed IDs are generated and how they are looked up using several options in has_prefix_id:
prefix: The string prefix (e.g., :acct).minimum_length: The minimum length of the hashed portion.salt: A specific salt for this model.fallback: If set to false, find will only accept prefixed IDs and will no longer accept regular integer primary keys.override_find: Boolean to enable/disable overriding Model.find.override_param: Boolean to enable/disable overriding to_param.class Account < ApplicationRecord
has_prefix_id :acct, minimum_length: 32, override_find: false, override_param: false, salt: "", fallback: false
endThe encode method converts a numeric ID into a prefixed, obfuscated string. The resulting format is {prefix}{delimiter}{hashid}. The internal hashid includes a constant TOKEN (123) to ensure the integrity of the encoded value.
Returns nil if the provided id is nil.
# Assuming prefix_id_handler is initialized with prefix 'user' and delimiter '/'
# and the internal hashid for ID 1 is 'abc'
prefix_id_handler.encode(1) # => "user/abc"The PrefixedIds.split_id(prefix_id, delimiter) method splits a string into its prefix component and its encoded ID component using the configured delimiter.
prefix, id = PrefixedIds.split_id("user_abc123")
# prefix => "user"
# id => "abc123"