Socket
Book a DemoInstallSign in
Socket

toolx

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

toolx

0.2.3
bundlerRubygems
Version published
Maintainers
1
Created
Source

Toolx

This gem adds a set of tools to enhance your Ruby on Rails application, providing utilities for envs, uniq ids, and more.

Installation

Install the gem and add to the application's Gemfile by executing:

$ bundle add toolx

Use rake tasks if needed:

bin/rails toolx:aliases:generate                             # Generate toolx_aliases.rb
bin/rails toolx:annotate:generate                            # Generate annotate rake tasks
bin/rails toolx:stateman:generate[model]                     # Generate StateMachine, Transition class, and migration

Add your toolx mixins to the ApplicationRecord or any other model:

class ApplicationRecord < ActiveRecord::Base
  primary_abstract_class

  include Toolx::Core::Concerns::Inquirer
  include Toolx::Core::Concerns::Transformer
  include Toolx::Core::Concerns::CustomIdentifier
  include Toolx::Core::Concerns::DateTimeToBoolean
  include Toolx::Core::Concerns::Keygen
  include Toolx::Core::Concerns::Tokenizer
  include Toolx::Core::Concerns::WithStateMachine
end

Features

Env

Access environment variables in a clean, expressive way.

ENV['ROLE'] = 'admin'

Env = Toolx::Core::Env

Env[:role]             # => "admin"
Env.role               # => "admin"
Env.role_.admin?       # => true
Env.role_.user?        # => false
Env.debug?             # => true/false (boolean cast)
Env.timeout!(10)       # => 10 (integer cast)
Env.role_(:none).none? # => true (inquiry cast)

CustomIdentifier

Generate a custom ID for the id column

CustomIdentifier = Toolx::Core::Concerns::CustomIdentifier

class User < ApplicationRecord
  include CustomIdentifier
  cid 'usr'
end

user.id # => "usr_Nc82xL0w92..."
CustomIdentifier = Toolx::Core::Concerns::CustomIdentifier

class Document < ApplicationRecord
  include CustomIdentifier
  belongs_to :workspace
  cid 'doc', related: { workspace: 4 }
end

# If workspace_id = "wsp_ABCXYZ...", then document id will be like:
# "doc_ABCXabcd123..."

Inquirer

Adds ? predicate-style behavior for strings.


class User < ApplicationRecord
  include Toolx::Core::Concerns::Inquirer

  inquirer :status, :kind
end

user = User.new(status: "active", kind: "admin")
user.status.active? # => true
user.status.inactive? # => false
user.kind.admin? # => true
user.kind.user?  # => false

Transformer

Transform input strings on assignment (e.g., strip, downcase, etc.)

class User < ApplicationRecord
  include Toolx::Core::Concerns::Transformer

  transform :email, :strip, :downcase
  transform :name, :strip, :presence
end

user = User.new
user.email = " Foo@Example.COM  "
user.name  = "   "

user.email # => "foo@example.com"
user.name  # => nil

DateTimeToBoolean

Use datetime fields as boolean-style flags:

class User < ApplicationRecord
  include Toolx::Core::Concerns::DateTimeToBoolean

  date_time_to_boolean :deleted_at
end

user.deleted?  # => false
user.deleted!  # sets deleted_at to current time
user.deleted = true  # also sets current time
user.deleted = false # sets deleted_at to nil

Keygen

Generate unique keys for your models, ensuring they are unique across the database.

class User < ApplicationRecord
  include Toolx::Core::Concerns::Keygen

  keygen :dob, attr: :lic_key, secret: 'my$ecret', limit: 20, separator: '.', br: 3
end
user = User.new(dob: '1990-01-01')
user.save! 
user.lic_key # => '090.cc2.207.c45.3e7.20b.f95'

Tokenizer

Generate unique tokens for your models before creation, useful for API keys, access tokens, invitations, etc.

class AccessToken < ApplicationRecord
  include Toolx::Core::Concerns::Tokenizer

  tokenize :token, size: 32, prefix: 'tok'
end

token = AccessToken.create!
token.token # => "tok-xnT3yM9dPQsA4W8Ks7LZhV5RuKcgByTw"

Stateman via with_state_machine

It is working only with Statesman::Adapters::ActiveRecord

You can generate state machine classes via rake task

bin/rails "toolx:stateman:generate[Project]"

command will generate models for existing Project model as Project::StateMachine and Project::Transition.

also will add migraion file for those models.

Example usage:

class Project::StateMachine
  include Statesman::Machine

  state :active, initial: true
  state :pending
  state :skipped
  state :cancelled
  state :done

  transition from: :active, to: [:pending, :pending, :skipped, :cancelled, :done]
  transition from: :pending, to: [:skipped, :cancelled, :done]
  transition from: :skipped, to: [:pending]

  after_transition do |model, transition|
    model.update!(status: transition.to_state)
  end
end

class Project::Transition < ActiveRecord::Base
  belongs_to :project

  attribute :most_recent, :boolean, default: false
  attribute :sort_key, :integer
  attribute :to_state, :string
  attribute :metadata, :json, default: {}

  validates :to_state, inclusion: { in: Project::StateMachine.states }
end

class Project < ActiveRecord::Base
  include Toolx::Core::Concerns::WithStateMachine
  STATUSES = %w[active pending done skipped cancelled].freeze

  with_state_machine

  attribute :name, :string
  attribute :status, :string, default: 'active'

  validates :name, presence: true
  validates :status, inclusion: { in: STATUSES }, allow_nil: true
end

Errors

A structured, extensible error-handling framework:

Wrap errors with nested backtrace info

class MyError < StandardError
  include Toolx::Core::Errors::NestedError
end

begin
  raise "Something failed"
rescue => e
  raise MyError.new("Outer error", e)
end

Base error classes

Toolx::Core::Errors::NestedStandardError
Toolx::Core::Errors::AppError
Toolx::Core::Errors::ApiError

Toolx::Core::Errors::BadRequest
Toolx::Core::Errors::Unauthorized
Toolx::Core::Errors::NotFound
Toolx::Core::Errors::Conflict
Toolx::Core::Errors::UnprocessableEntity
Toolx::Core::Errors::FailedDependency
Toolx::Core::Errors::Forbidden
Toolx::Core::Errors::InternalServerError
Toolx::Core::Errors::BadGateway
Toolx::Core::Errors::ServiceUnavailable
Toolx::Core::Errors::GatewayTimeout

Form

A simple form builder for Rails applications:

class Space::InfoForm < Toolx::Core::Form
  attribute :name, :string
  attribute :description, :string
  attribute :kind, :string

  validates :name, presence: true
  validates :kind, inclusion: { in: Space::KINDS }, allow_blank: true
end

Presenter

Elegant presenter base class wrapping any object, with I18n support and flexible invocation patterns.

class UserPresenter < Toolx::Core::Presenter
  def display_name
    name.upcase
  end
end

UserPresenter.present(user).display_name # => "ALICE"

to_proc usage

users.map(&UserPresenter) # => wraps each user

as_proc(use: :method) usage

users.map(&UserPresenter.as_proc(use: :display_name))

auto_present detection

class Article
  class Presenter < ::Toolx::Core::Presenter
    def short_title = title.truncate(10)
  end
end

Presenter.auto_present(Article.new(title: "A very long title"))

SimpleCrypt

Simple AES encryption helper using ActiveSupport::MessageEncryptor.

Toolx::Core::SimpleCrypt.encrypt('hello') # => encrypted string
Toolx::Core::SimpleCrypt.decrypt(encrypted_string) # => "hello"
  • Uses ENV['CRYPT_SECRET'] or Rails credentials by default.
  • You can pass a custom secret: if needed.
encrypted = Toolx::Core::SimpleCrypt.encrypt('secret info', secret: 'a' * 32)
Toolx::Core::SimpleCrypt.decrypt(encrypted, secret: 'a' * 32) # => 'secret info'

❗️ Errors

  • MissingSecretError – when no secret is configured
  • EncryptionError – on encryption failure
  • DecryptionError – on verification or decoding failure

Operation

A base class for service operations, providing a structured way to define and execute business logic with typed parameters and responses.

class Country::Code < Toolx::Core::Operation
  self.transactional = false # When we do not need transaction support, by default it is true
  simplified_result :value

  params { attribute :source, Types.Instance(ISO3166::Country) | Types::Coercible::String }
  response { attribute :value, Types::Symbol }

  def perform = { value: Country::Object[source:].alpha2.to_sym }

  private

  delegate :source, to: :params
end
# when simplified_result is used it is possible to use it like this:
source = 'Polska'
Country::Code[source:] # => :PL
Country::Code.call(source:) # => :PL
Country::Code.(source:) # => :PL
# And default one 
Country::Code.new(source:).perform.value # => :PL

Operation provides accessories like params, response but it can be used as Param and Response classes as well.

class Country::Code < Toolx::Core::Operation
  self.transactional = false # When we do not need transaction support
  # callback :before, :after, :around, etc. can be used to add hooks
  after -> { 'send notification' }
  before :validate!
  
  rescue_from ActiveRecord::RecordInvalid, with: :raise_something
  
  class Params 
    attribute :source, Types.Instance(ISO3166::Country) | Types::Coercible::String }
  end
  
  class Response
    attribute :value, Types::Symbol
  end

  def perform = { value: Country::Object[source:].alpha2.to_sym }

  private
  
  def validate! = true
  
  def raise_something(exception)
    raise Toolx::Core::Errors::BadRequest, "Invalid source: #{exception.message}"
  end

  delegate :source, to: :params
end

Operation::Flow

A streamlined interface for orchestrating and executing service operations with support for:

  • typed parameters (via Dry::Types)
  • typed responses (with translation helpers & inquiry methods)
  • flow control (.on_success, .on_fail, .bind_with, .perform, etc.)
class SignupOperation < Toolx::Core::Operation
  include Toolx::Core::Operation::Flow

  params do
    attribute :email, Types::String
    attribute :age, Types::Integer
  end

  response do
    include Toolx::Core::Concerns::Inquirer
    attribute :status, Types::String
    attribute :message, Types::String
    inquirer :status
  end

  def perform
    if age < 18
      { status: 'error', message: 'You must be 18+' }
    else
      { status: 'success', message: "Welcome, #{email}" }
    end
  end
end

🚀 Execution Flow

Initialize, perform, and access result:

flow = SignupOperation.flow
executor = flow.perform(email: 'foo@bar.com', age: 20)

executor.response.status.success? # => true
executor.response.message         # => "Welcome, foo@bar.com"

Retry logic:

executor.perform!                # Re-executes with same params
executor.perform!(email: ..., age: ...) # Replaces and re-executes

🔁 Handler Bindings

Symbolic method bindings:

SignupOperation.flow
  .bind_with(self)
  .on(success: :redirect_to_dashboard, fail: :render_form)
  .perform(email: 'foo@bar.com', age: 17)

Proc-style handler chaining:

SignupOperation.flow
  .on_success { |resp, exec| notify_user(resp.message) }
  .on_fail { |resp, exec| logger.warn("Failed: #{resp.message}") }
  .perform!(email: 'foo@bar.com', age: 20)

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Toolx project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

FAQs

Package last updated on 30 Jun 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.