A Ruby on Rails integration for Typesense search engine that provides seamless integration with ActiveRecord, Sequel and Mongoid models.
This gem is a fork of the algolia-rails gem, adapted to work with Typesense while maintaining similar functionality and API patterns. The core integration patterns and much of the functionality were inspired by Algolia's excellent work. Special thanks to the Algolia team for their original implementation, which provided a solid foundation for this Typesense integration.
- Seamless integration with ActiveRecord, Sequel, and Mongoid models
- Automatic indexing of model data with callbacks
- Support for multiple pagination backends (Kaminari, WillPaginate, Pagy)
- Rich attribute customization and serialization
- Support for nested relationships and hierarchical data
- Background job processing via ActiveJob integration
- Conditional indexing based on model state
- Environment-specific indexing
- Support for faceted search and filtering
- Customizable schema with predefined fields
- Multi-way and one-way synonyms support
- Rake tasks for index management
Add this line to your application's Gemfile:
gem 'typesense-rails', '~> 1.0.0.rc1'
Then execute:
$ bundle install
Initialize Typesense in your Rails application (e.g., in config/initializers/typesense.rb
):
Typesense.configuration = {
nodes: [{
host: 'localhost', # For Typesense Cloud use xxx.a1.typesense.net
port: '8108', # For Typesense Cloud use 443
protocol: 'http' # For Typesense Cloud use https
}],
api_key: 'your-api-key',
connection_timeout_seconds: 2
}
class Product < ApplicationRecord
include Typesense
typesense do
# Define attributes to be indexed
attributes :name, :description, :price
# Add dynamic attributes
attribute :full_name do
"#{first_name} #{last_name}"
end
# Define predefined fields with specific types
predefined_fields [
{ 'name' => 'name', 'type' => 'string', 'facet' => true },
{ 'name' => 'price', 'type' => 'float' }
]
# Set default sorting
default_sorting_field 'price'
# Configure synonyms
multi_way_synonyms [
{ "phone-synonym" => %w[galaxy samsung samsung_electronics] }
]
one_way_synonyms [
{ "smart-phone-synonym" => {
"root" => "smartphone",
"synonyms" => %w[nokia samsung motorola android]
}
}
]
# Symbols to index
symbols_to_index ["-", "_"]
# Token separators
token_separator ["-", "_"]
# Enable nested fields
enable_nested_fields true
end
end
class Profile < ApplicationRecord
include Typesense
belongs_to :user
has_many :specializations
typesense do
# Nest user data
attribute :user do
{ name: user.name, email: user.email }
end
# Include related data
attribute :specializations do
specializations.select(&:public?).map do |s|
{ title: s.title, category: s.category }
end
end
end
end
# Basic search
results = Product.search('phone', 'name')
# Search with filters and sorting
results = Product.search('phone', 'name', {
filter_by: 'price:< 500',
sort_by: 'price:asc'
})
# Faceted search
results = Product.search('*', '', {
facet_by: 'category',
per_page: 20
})
# Reindex all records (with zero-downtime)
Product.reindex
# Regular reindexing (overwrites existing records)
Product.reindex!
# Index specific records
Product.where('updated_at > ?', 10.minutes.ago).reindex!
# Index a single record
product.index!
# Remove from index
product.remove_from_index!
# Conditional indexing
typesense if: :published?, unless: :draft? do
# indexing configuration
end
Process indexing operations asynchronously using ActiveJob:
class Product < ApplicationRecord
include Typesense
typesense enqueue: true do
attributes :name, :description, :price
end
end
Or define custom job processing:
class Product < ApplicationRecord
include Typesense
typesense enqueue: :trigger_worker do
attributes :name, :description, :price
end
def self.trigger_worker(record, remove)
IndexingWorker.perform_async(record.id, remove)
end
end
The gem supports multiple pagination backends:
# Configure pagination backend
Typesense.configuration = {
# ... other configuration ...
pagination_backend: :kaminari # or :will_paginate or :pagy
}
To run the test suite:
bundle install
bundle exec rake
- Fork the repository
- Create your feature branch (
git checkout -b feature/my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin feature/my-new-feature
) - Create a new Pull Request
Please make sure to update tests as appropriate and follow the existing coding style.
To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
This project is licensed under the MIT License - see the LICENSE file for details.