Today I Learned

Working with ElasticSearch and Rails; part 2

A typical setup for a Ruby on Rails app and Elasticsearch is built around the elasticsearch-model, elasticsearch-rails, elasticsearch-persistence and elasticsearch-dsl bundle.

One of the facilities of the aforementioned bundle is that they “automagically” refreshes the appropriate indexes in an atomic way, mainly thanks to this callback you have set on a related model:

  after_commit on: [:create] do
    __elasticsearch__.index_document
  end

  after_commit on: [:update] do
    __elasticsearch__.update_document
  end

  after_commit on: [:destroy] do
    __elasticsearch__.delete_document
  end

Thing is, as the development continues, it’s easy to end up with some “composite” indexed values, where a several database fields are taken into consideration when calculating the final value. Example:

def as_indexed_json(_options = {})
 {
   branch: branch_names
 }
end

def branch_names
 Array.new.tap do |ary|
   ary << "cleaning" if provides_cleaning_services.present?
   ary << "accommodation" if provides_accommodation_services.present?
   ary << "food_service" if has_alcohol_license.present?
 end.presence || ["no_branch"]
end

Sadly, updating any of the database fields impacting the branch_names index value won’t trigger the branch_names field refresh. Instead of waiting for a client to file a bug report (and making him unhappy in general) consider overwriting one of these callbacks to something along these lines:

after_commit on: [:update] do
  if self.previous_changes.present?
    __elasticsearch__.index_document
  end
end