{"record":{"id":"09ffc43b8ee9882a","repo":"thoughtbot/shoulda-matchers","slug":"need-at-least-one-attribute","errorCode":null,"errorMessage":"need at least one attribute","messagePattern":"need at least one attribute","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/shoulda/matchers/active_record/normalize_matcher.rb","lineNumber":70,"sourceCode":"      #     end\n      #\n      #     # RSpec\n      #     RSpec.describe User, type: :model do\n      #       it { should normalize(:name).from(\"jane doe\").to(\"Jane Doe\") }\n      #       it { should normalize(:name).from(nil).to(\"Untitled\") }\n      #     end\n      #\n      #     # Minitest (Shoulda)\n      #     class User < ActiveSupport::TestCase\n      #       should normalize(:name).from(\"jane doe\").to(\"Jane Doe\")\n      #       should normalize(:name).from(nil).to(\"Untitled\")\n      #     end\n      #\n      # @return [NormalizeMatcher]\n      #\n      def normalize(*attributes)\n        if attributes.empty?\n          raise ArgumentError, 'need at least one attribute'\n        else\n          NormalizeMatcher.new(*attributes)\n        end\n      end\n\n      # @private\n      class NormalizeMatcher\n        attr_reader :attributes, :from_value, :to_value, :failure_message,\n          :failure_message_when_negated\n\n        def initialize(*attributes)\n          @attributes = attributes\n        end\n\n        def description\n          %(\n            normalize #{attributes.to_sentence(last_word_connector: ' and ')} from\n            ‹#{from_value.inspect}› to ‹#{to_value.inspect}›","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/thoughtbot/shoulda-matchers/blob/79cdfbc326e97c9b43991b644434ca53c1f62c4c/lib/shoulda/matchers/active_record/normalize_matcher.rb#L52-L88","documentation":"Error \"need at least one attribute\" thrown in thoughtbot/shoulda-matchers.","triggerScenarios":"Thrown at lib/shoulda/matchers/active_record/normalize_matcher.rb:70 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"79cdfbc326e97c9b43991b644434ca53c1f62c4c","analyzedAt":"2026-08-23T09:43:24.200Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}