Integrations
/
Frameworks
/
Rails
/
Working with Relationships
Feb. 27, 2019
Working with Relationships
Serializing relationships
You can easily embed nested objects defining an extra attribute returning any JSON-compliant object (an array or a hash or a combination of both).
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
Propagating change from a nested relation
With ActiveRecord
With ActiveRecord, we’ll be using touch
and after_touch
to achieve this.
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 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
With Sequel
With Sequel, you can use the touch
plugin to propagate the changes:
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 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