Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/ruby_llm/active_record/acts_as_legacy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,8 @@ def prepare_for_active_storage(attachments)
case attachment
when ActionDispatch::Http::UploadedFile, ActiveStorage::Blob
attachment
when ActiveStorage::Attached::One, ActiveStorage::Attached::Many
attachment.blobs
when ActiveStorage::Attachment
attachment.blob
when Hash
attachment.values.map { |v| prepare_for_active_storage(v) }
else
Expand Down
4 changes: 2 additions & 2 deletions lib/ruby_llm/active_record/chat_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ def prepare_for_active_storage(attachments)
case attachment
when ActionDispatch::Http::UploadedFile, ActiveStorage::Blob
attachment
when ActiveStorage::Attached::One, ActiveStorage::Attached::Many
attachment.blobs
when ActiveStorage::Attachment
attachment.blob
when Hash
attachment.values.map { |v| prepare_for_active_storage(v) }
else
Expand Down
6 changes: 6 additions & 0 deletions spec/dummy/app/models/document.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class Document < ApplicationRecord
has_one_attached :file
has_many_attached :files
end
10 changes: 10 additions & 0 deletions spec/dummy/db/migrate/20251002152808_create_documents.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

class CreateDocuments < ActiveRecord::Migration[7.0]
def change
create_table :documents do |t|
t.string :title
t.timestamps
end
end
end
8 changes: 7 additions & 1 deletion spec/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 20_250_602_134_116) do
ActiveRecord::Schema[8.0].define(version: 20_251_002_152_808) do
create_table 'active_storage_attachments', force: :cascade do |t|
t.string 'name', null: false
t.string 'record_type', null: false
Expand Down Expand Up @@ -49,6 +49,12 @@
t.index ['model_id'], name: 'index_chats_on_model_id'
end

create_table 'documents', force: :cascade do |t|
t.string 'title'
t.datetime 'created_at', null: false
t.datetime 'updated_at', null: false
end

create_table 'messages', force: :cascade do |t|
t.integer 'chat_id'
t.string 'role'
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

35 changes: 26 additions & 9 deletions spec/ruby_llm/active_record/acts_as_attachment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,45 @@ def uploaded_file(path, type)
expect(llm_message.content.attachments.first.mime_type).to eq('image/png')
end

it 'handles multiple attachments' do
it 'handles ActiveStorage::Attached::One in ask method' do
chat = Chat.create!(model: model)

image_upload = uploaded_file(image_path, 'image/png')
pdf_upload = uploaded_file(pdf_path, 'application/pdf')
document = Document.create!(title: 'Test Document')
document.file.attach(
io: File.open(image_path),
filename: 'ruby.png',
content_type: 'image/png'
)

response = chat.ask('Analyze these', with: [image_upload, pdf_upload])
response = chat.ask('What do you see?', with: document.file)

user_message = chat.messages.find_by(role: 'user')
expect(user_message.attachments.count).to eq(2)
expect(user_message.attachments.count).to eq(1)
expect(user_message.attachments.first.filename.to_s).to eq('ruby.png')
expect(response.content).to be_present
end

it 'handles attachments in ask method' do
it 'handles ActiveStorage::Attached::Many in ask method' do
chat = Chat.create!(model: model)

image_upload = uploaded_file(image_path, 'image/png')
document = Document.create!(title: 'Test Document')
document.files.attach(
io: File.open(image_path),
filename: 'ruby.png',
content_type: 'image/png'
)
document.files.attach(
io: File.open(pdf_path),
filename: 'sample.pdf',
content_type: 'application/pdf'
)

response = chat.ask('What do you see?', with: image_upload)
response = chat.ask('Analyze these', with: document.files)

user_message = chat.messages.find_by(role: 'user')
expect(user_message.attachments.count).to eq(1)
expect(user_message.attachments.count).to eq(2)
filenames = user_message.attachments.map { |a| a.filename.to_s }.sort
expect(filenames).to eq(['ruby.png', 'sample.pdf'])
expect(response.content).to be_present
end
end
Expand Down
14 changes: 7 additions & 7 deletions spec/ruby_llm/active_record/acts_as_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -448,28 +448,28 @@ def uploaded_file(path, type)
expect(llm_message.content.attachments.first.mime_type).to eq('image/png')
end

it 'handles multiple attachments' do
it 'handles a single attachment in ask method' do
chat = Chat.create!(model: model)

image_upload = uploaded_file(image_path, 'image/png')
pdf_upload = uploaded_file(pdf_path, 'application/pdf')

response = chat.ask('Analyze these', with: [image_upload, pdf_upload])
response = chat.ask('What do you see?', with: image_upload)

user_message = chat.messages.find_by(role: 'user')
expect(user_message.attachments.count).to eq(2)
expect(user_message.attachments.count).to eq(1)
expect(response.content).to be_present
end

it 'handles attachments in ask method' do
it 'handles multiple attachments in ask method' do
chat = Chat.create!(model: model)

image_upload = uploaded_file(image_path, 'image/png')
pdf_upload = uploaded_file(pdf_path, 'application/pdf')

response = chat.ask('What do you see?', with: image_upload)
response = chat.ask('Analyze these', with: [image_upload, pdf_upload])

user_message = chat.messages.find_by(role: 'user')
expect(user_message.attachments.count).to eq(1)
expect(user_message.attachments.count).to eq(2)
expect(response.content).to be_present
end

Expand Down