I think previous answers help in the encryption part, but no one adresses the first part of the question:
...such that people can't view various records simply by guessing different integer IDs
As Matt Rohrer answered here to be able to access the resource only through the encrypted ID you could use friendly_id this way:
models/plan.rb
class Plan < ApplicationRecord
extend FriendlyId
friendly_id :hashed_id #hashed_id is already a plan column
validates :hashed_id, uniqueness: true
before_create :generate_hash
def generate_hash
# This way you ensure the hash contains letters or numbers but is not very secure
all_letters = [('A'..'Z'), ('a'..'z'), ('0'..'9')].map(&:to_a).flatten
random_string = (0...8).map { all_letters[rand(36)] }.join
self.hashed_id = random_string
end
controllers/plans_controller.rb
class PlansController < ApplicationController
before_action :set_plan, only: [:show, :edit, :update, :destroy]
...
private
def set_plan
# This allows accessibility to plans only through hashed_id
@plan = Plan.find_by!(hashed_id: params[:id])
end
end
If you want a more secure encryption you should use SecureRandom or digest/sha1, maybe these examples can help.