Update embedding vector column with Ruby Array embedding data

This error is from a missing Ruby ↔ PostgreSQL vector type adapter.

Your PostgreSQL column is:

embedding vector(1024)

but Ruby is passing:

[0.00814, 0.05109, ...]

as a normal Array. ActiveRecord doesn’t automatically know how to quote a Ruby Array as a pgvector value, hence:

can't quote Array (TypeError)

The pgvector Ruby project itself says Rails should use Neighbor for ActiveRecord support; the pgvector gem alone supports the lower-level pg library, not ActiveRecord directly. (GitHub)

Let’s fix this properly rather than hacking SQL.

Step 13.1 – Add Neighbor

Neighbor is the Ruby/ActiveRecord integration we’ll use for vector columns and nearest-neighbor queries.

https://github.com/ankane/neighbor

Add to your Gemfile:

gem "neighbor"

Then:

bundle install

Check:

bundle info neighbor

Step 13.2 – Configure Neighbor

Open:

config/initializers/neighbor.rb

Create it if it doesn’t exist.

Add:

Neighbor.configure do |config|
config.neighbor_search_class = "Neighbor::Vector"
end

However, don’t add this configuration blindly yet. Neighbor’s Rails integration has version-dependent setup, and I don’t want to introduce unnecessary configuration if your installed version doesn’t require it.

First check:

bundle info neighbor

and:

bin/rails c

Then:

Neighbor

If that resolves, we’re good.

Step 13.3 – Add the vector support to DocumentChunk

Open:

app/models/document_chunk.rb

Add:

class DocumentChunk < ApplicationRecord
belongs_to :document
has_neighbors :embedding
validates :content, presence: true
validates :chunk_index, presence: true
end

The important part:

has_neighbors :embedding

This tells Neighbor:

embedding is a vector field that should participate in nearest-neighbor operations.

Neighbor’s Rails integration provides ActiveRecord support for vector columns and nearest-neighbor search. (Stack Overflow)

Step 13.4 – Restart Rails console

Exit any existing console:

exit

Then:

bin/rails c

Reload:

DocumentChunk.reset_column_information

Now:

DocumentChunk.first

Check:

DocumentChunk.first.embedding

At the moment it might be nil, which is fine.

Step 13.5 – Save the embedding

Now try your existing embedding:

chunk = DocumentChunk.first
embedding = Ai::EmbeddingService.new.call(
text: chunk.content
)

Then:

chunk.update!(embedding: embedding)

This should now work.

The important change is that Neighbor teaches ActiveRecord how to handle the PostgreSQL vector type instead of treating your Ruby array as a generic PostgreSQL value.

Step 13.6 – Verify

Run:

chunk.reload

Then:

chunk.embedding.length

Expected:

1024

And:

chunk.embedding.first(5)

should return the vector values.

Also verify directly:

bin/rails dbconsole
SELECT
id,
vector_dims(embedding)
FROM document_chunks
WHERE embedding IS NOT NULL;

Expected:

 id | vector_dims
----+------------
  1 | 1024

Why this happened

This is an important RAG/Rails lesson.

We have three different layers:

Ruby
Array<Float>
ActiveRecord
PostgreSQL
vector(1024)

ActiveRecord knows how to serialize things like:

string
integer
json
datetime

but vector is a PostgreSQL extension type.

So we need an adapter:

Ruby Array
Neighbor / pgvector integration
PostgreSQL vector

The low-level pgvector Ruby gem can register the vector type with the pg driver, but for ActiveRecord, the pgvector project points Rails users toward Neighbor.

One correction to our earlier Step 13

I previously implied:

t.vector :embedding, limit: 1024

was enough for Rails.

That’s only the database schema side.

We also need the ActiveRecord integration layer.

So the complete architecture is:

PostgreSQL
├── vector extension
└── vector(1024)
Neighbor
ActiveRecord
DocumentChunk

This distinction is worth remembering for interviews:

Installing pgvector in PostgreSQL creates the vector type and operators; Rails still needs an ActiveRecord integration to properly serialize and query that type.

Don’t move to similarity search yet

First make this work:

chunk.update!(embedding: embedding)

Then:

chunk.embedding.length
# => 1024

Once that succeeds, we’ll immediately do the important part:

Step 13.3 – Semantic Search

We’ll build:

Ai::VectorSearchService

and run:

"What allows Ruby code to be reused?"
query embedding
pgvector cosine similarity
DocumentChunk
"Ruby modules allow code to be organized and reused."

That will give you your first real semantic search/RAG retrieval.