From 88576488f0317a1d0bea2929e70de3189d0d6ab6 Mon Sep 17 00:00:00 2001 From: Kenta Ishizaki Date: Fri, 17 Apr 2026 07:50:53 +0900 Subject: [PATCH] Add Content#empty? to fix Anthropic NoMethodError Fixes #729 RubyLLM::Content did not implement #empty?, causing NoMethodError in Anthropic provider code paths that check `msg.content.nil? || msg.content.empty?` when content is a Content instance (e.g. messages with ActiveStorage attachments). Content#empty? now returns true when text is blank (nil, empty, or whitespace-only) and there are no attachments, consistent with String#empty? and Array#empty? semantics. --- lib/ruby_llm/content.rb | 4 ++++ spec/ruby_llm/content_spec.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 spec/ruby_llm/content_spec.rb diff --git a/lib/ruby_llm/content.rb b/lib/ruby_llm/content.rb index d4010c4ba..1a9a27742 100644 --- a/lib/ruby_llm/content.rb +++ b/lib/ruby_llm/content.rb @@ -26,6 +26,10 @@ def format end end + def empty? + @text.to_s.strip.empty? && @attachments.empty? + end + # For Rails serialization def to_h { text: @text, attachments: @attachments.map(&:to_h) } diff --git a/spec/ruby_llm/content_spec.rb b/spec/ruby_llm/content_spec.rb new file mode 100644 index 000000000..70dc44c1a --- /dev/null +++ b/spec/ruby_llm/content_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe RubyLLM::Content do + describe '#empty?' do + it 'is true when text is empty and there are no attachments' do + expect(described_class.new('')).to be_empty + end + + it 'is true when text is whitespace-only and there are no attachments' do + expect(described_class.new(" \n\t")).to be_empty + end + + it 'is false when text has content' do + expect(described_class.new('hello')).not_to be_empty + end + + it 'is false when attachments are present without text' do + content = described_class.new(nil, 'spec/fixtures/ruby.txt') + expect(content).not_to be_empty + end + + it 'is false when both text and attachments are present' do + content = described_class.new('hello', 'spec/fixtures/ruby.txt') + expect(content).not_to be_empty + end + end +end