Open-source project
hashie/hashie avatar
hashie/hashie

Hashie: mixin modules that give Ruby hashes coercion, method access and deep merging

Hashie is a collection of classes and mixins that make Ruby hashes more powerful.

3,037 stars313 forksRubyMIT

At a glance

What is it?
Hashie is a Ruby gem that splits hash behaviour into separately includable modules, from indifferent access to typed coercion. It suits API clients and lightweight data models, and it is a poor fit where a plain Struct or a schema library already does the job.
Who is it for?
Adopt Hashie when you are modelling API payloads in Ruby and want per-class control over key access, coercion and deep merging without a schema DSL. Do not adopt it as a general replacement for Struct, Data or a validation library, and do not expect built-in boolean coercion, since the README states Ruby has no standard method for it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 35 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Hashie targets: hashes that need behaviour, not just storage

A Ruby hash is a container. The moment a hash represents a domain object, you start writing the same code around it: normalising string keys to symbols, converting a nested hash into an object, merging nested configuration without clobbering siblings, raising when a required key is missing. Hashie packages those behaviours as modules you include one at a time rather than as a framework you adopt wholesale.

The README describes the library as "a growing collection of tools that extend Hashes and make them more useful", and the structure bears that out. The table of contents lists Hash Extensions separately from the composite classes Mash, Dash, Trash, Clash and Rash. You can include Hashie::Extensions::Coercion on a class that inherits from Hash and get typed coercion without taking on Mash's method-access semantics. That granularity is the point. It is aimed at library authors and application developers building API clients or configuration objects, not at people who want a full object-mapping layer.

How the extension modules compose into a hash subclass

The mechanism is Ruby module inclusion. Any extension can be mixed into a class with include Hashie::Extensions::ExtensionName, and each module hooks into the hash's write path or read path independently. MergeInitializer changes construction so that initialize accepts a hash and merges it in. Coercion adds class-level coerce_key and coerce_value declarations that intercept assignment. MethodAccess generates reader methods for keys. IndifferentAccess makes string and symbol keys resolve to the same entry.

Coercion is the most involved. A key coercion looks up a class and calls either its coerce class method or its constructor, in that order. Value coercions fire based on the type of the value being inserted, which is how a self-propagating hash is built. Collections and hashes have their own forms: coerce_key :mentions, Array[User] coerces each element, and coerce_key :relations, Hash[User => Relation] coerces keys and values separately. Core types map to standard Ruby conversion methods, and the README is explicit that these are permissive: it notes that "foo".to_i returns 0 rather than raising. That is a real trap for anyone treating coercion as validation.

There is also a documented structural limit. Because coerce_key is a class-level method, two classes cannot coerce to each other directly; the README states you cannot have circular coercion without the use of a proc. The logger is a single module-level setting, replaced with Hashie.logger = Rails.logger, and it defaults to STDOUT.

Installing Hashie and building a first coercing hash

Hashie ships as a RubyGem. The README gives the install command directly, and there is no separate setup step or configuration file to create.

bash
gem install hashie

In a bundled application you would add the gem to your Gemfile instead, then require it. The README's own example builds a lightweight API model by including three modules: Coercion for typed keys, MergeInitializer so the constructor accepts a hash, and MethodAccess is available separately if you want reader methods. The example below is copied from the README's Tweet class, including the coerce_key declaration.

ruby
class Tweet < Hash
  include Hashie::Extensions::Coercion
  include Hashie::Extensions::MergeInitializer
  coerce_key :user, User
end

user_hash = { name: "Bob" }
Tweet.new(user: user_hash)

What you should see is that passing a plain hash under the :user key returns a User instance, because Hashie calls User.coerce(user_hash) or falls back to User.new(user_hash) when that class method is not defined. If neither exists, the coercion fails at assignment time. For a boolean field, the README shows a custom proc passed to coerce_key, matching strings against a pattern like /\A(true|t|yes|y|1)\z/i and handling Numeric and other values in the else branch. That proc is the documented workaround, not a built-in type.

Where Hashie stops being the right tool

Coercion is not validation. The core-type table routes Integer, Float, Complex, Rational, String and Symbol through Ruby's own to_i, to_f, to_c, to_r, to_s and to_sym. Those methods are lenient by design, and the README calls this out with the example that "foo".to_i returns 0. If your input can be malformed, Hashie will happily produce a zero and your code will carry on. Reach for a validation layer if that matters.

Boolean coercion has no built-in support at all. The README explains why: Ruby has no built-in boolean type or standard method for coercing to a boolean. Every project that needs it writes the same proc. That is a small but repeated cost.

Circular coercion is the other hard edge. Because the declarations live at class level, a CategoryHash that coerces :products to Array[ProductHash] cannot be mirrored by ProductHash coercing back to CategoryHash without a proc. The README states this limitation plainly. Finally, mixing many extensions into a hash subclass produces an object whose behaviour is spread across several modules, and the README does not document rollback or a way to inspect which coercion rule fired. Debugging a surprising value means reading the included modules yourself.

Hashie compared with a plain Struct or a schema library

The closest thing in the standard library is Struct, and the difference is in the access model. A Struct fixes its members at class definition time and raises NoMethodError for anything else. A Hashie::Mash accepts arbitrary keys and exposes them as methods, which is what makes it convenient for API responses whose shape you do not control. The trade-off runs the other way too: a typo in a Mash key silently creates a new entry unless you include IgnoreUndeclared or use StrictKeyAccess, whereas a Struct fails loudly.

Against a schema or validation library, the difference is where the rules live. Hashie attaches coercion to the hash class through class-level declarations and leaves validation to you. A schema library typically declares types and constraints together and rejects bad input. Hashie's DeepMerge, DeepFetch, DeepFind and DeepLocate extensions address traversal, which schema libraries generally do not, so the two are not strict substitutes. If your problem is nested configuration merging, Hashie covers ground a validator does not.

Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-08-25. The most recent release is v5.1.0 from 2025-12-24, following v5.0.0 in 2022 and v4.1.0 in 2020. That release spacing is worth noting: major versions are years apart, so a 5.x upgrade is a deliberate project, not a routine bump. The README states it documents the next release, 5.1.1, while the current stable release is 5.1.0, so the default branch runs slightly ahead of the published gem.

The repository carries UPGRADING.md and CHANGELOG.md at the top level, which is where the cost of moving between major versions is recorded. Anyone pinning Hashie should read UPGRADING.md before a major bump rather than assuming the extension modules behave identically across versions. Hashie is MIT licensed, which permits commercial and closed-source use; the LICENSE file is at the repository root. That is a statement about the licence text, not legal advice for your situation.

Editorial conclusion

Adopt Hashie when you are modelling API payloads in Ruby and want per-class control over key access, coercion and deep merging without a schema DSL. Do not adopt it as a general replacement for Struct, Data or a validation library, and do not expect built-in boolean coercion, since the README states Ruby has no standard method for it. Before committing, read UPGRADING.md for the 5.x changes and check which extension modules your classes actually include, because the library is designed to be mixed in piecemeal and a missing module is a silent behavioural difference, not an error.

Frequently asked questions

What is a Hashie?

Hashie is a Ruby gem described in its README as a collection of tools that extend Hashes and make them more useful. It is organised as separately includable extension modules plus composite classes such as Mash, Dash, Trash, Clash and Rash.

How do I install the Hashie gem?

The README gives a single command, gem install hashie, and notes that Hashie is available as a RubyGem. There is no separate installer or configuration step documented.

Can Hashie coerce values to booleans?

Not with a built-in type. The README states Hashie has no built-in support for coercing booleans because Ruby has no built-in boolean type or standard coercion method, and shows a custom proc passed to coerce_key as the way to do it.

Can two Hashie classes coerce to each other in a cycle?

Not directly. The README explains that because coerce_key is a class-level method, circular coercion is not possible without the use of a proc.

What is the current stable release of Hashie?

The README states that the current stable release is 5.1.0, while the documentation being read covers the next release, 5.1.1. The v5.1.0 tag is dated 2025-12-24.

Official sources

  1. hashie/hashie on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hashie-hashie.svg)](https://hysenlabs.com/projects/hashie-hashie)