diff --git a/gnu/packages/ruby.scm b/gnu/packages/ruby.scm
index 0dc3561fbb2d8a95686ff0bf84891b0613e0e9e5..d876f57b6100d8bdd1eb7052510c1c1a7c9869ab 100644
--- a/gnu/packages/ruby.scm
+++ b/gnu/packages/ruby.scm
@@ -3219,6 +3219,44 @@ (define-public ruby-shoulda-context
     (home-page "https://github.com/thoughtbot/shoulda-context")
     (license license:expat)))
 
+(define-public ruby-shoulda-matchers
+  (package
+    (name "ruby-shoulda-matchers")
+    (version "3.0.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (rubygems-uri "shoulda-matchers" version))
+       (sha256
+        (base32
+         "1agabvb8i39mjrp3kb78nvhl41xk1i258hdwdlj0fm8nj9yzn1jb"))))
+    (build-system ruby-build-system)
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-before 'build 'fix-import
+           (lambda _
+             ;; A presumed bug reported upstream at
+             ;; https://github.com/thoughtbot/shoulda-matchers/pull/871
+             (substitute* (string-append  "lib/shoulda/matchers/active_model/"
+                                          "validate_inclusion_of_matcher.rb")
+               (("^require 'bigdecimal'")
+                "require 'bigdecimal'; require 'date'"))))
+         (replace 'check
+           (lambda _
+             ;; Do not run tests to avoid circular dependence with rails.  Instead
+             ;; just import the library to test.
+             (zero? (system* "ruby" "-Ilib" "-r" "shoulda-matchers")))))))
+    (propagated-inputs
+     `(("ruby-activesupport" ,ruby-activesupport)))
+    (synopsis "Collection of testing matchers extracted from Shoulda")
+    (description
+     "Shoulda Matchers provides RSpec- and Minitest-compatible one-liners that
+test common Rails functionality.  These tests would otherwise be much longer,
+more complex, and error-prone.")
+    (home-page "https://github.com/thoughtbot/shoulda-matchers")
+    (license license:expat)))
+
 (define-public ruby-ansi
   (package
     (name "ruby-ansi")