To represent relationships and hierarchical structures in your ,
you can embed nested objects within your attributes.
These nested objects can be arrays,
hashes, or a combination of both,
provided they can be converted into JSON.
class Profile < ActiveRecord::Base
include AlgoliaSearch
belongs_to :user
has_many :specializations
algoliasearch do
attribute :user do
# restrict the nested "user" object to its `name` + `email`
{ name: user.name, email: user.email }
end
attribute :public_specializations do
# build an array of public specialization (include only `title` and `another_attr`)
specializations.select { |s| s.public? }.map do |s|
{ title: s.title, another_attr: s.another_attr }
end
end
end
end
Update changes from nested relations with ActiveRecord
To update changes with nested relations using ActiveRecord, use touch and after_touch.
# app/models/app.rb
class App < ApplicationRecord
include AlgoliaSearch
belongs_to :author, class_name: :User
after_touch :index!
algoliasearch do
attribute :title
attribute :author do
author.as_json
end
end
end
# app/models/user.rb
class User < ApplicationRecord
# If your association uses belongs_to
# - use `touch: true`
# - do not define an `after_save` hook
has_many :apps, foreign_key: :author_id
after_save { apps.each(&:touch) }
end
Update changes from nested relations with Sequel
With Sequel, you can use the touch plugin to propagate the changes:
# app/models/app.rb
class App < Sequel::Model
include AlgoliaSearch
many_to_one :author, class: :User
plugin :timestamps
plugin :touch
algoliasearch do
attribute :title
attribute :author do
author.to_hash
end
end
end
# app/models/user.rb
class User < Sequel::Model
one_to_many :apps, key: :author_id
plugin :timestamps
# Can't use the associations since it won't trigger the after_save
plugin :touch
# Define the associations that need to be touched here
# Less performant, but allows for the after_save hook to trigger
def touch_associations
apps.map(&:touch)
end
def touch
super
touch_associations
end
end
Last modified on March 12, 2026