I have a multi-tenant rails-api project with rails 4.2.3 and ruby 2.2.2. I found lots of resources out there for dealing with multi-tenancy with rails and postgres, but not much regarding elasticsearch and more specifically the chewy gem. I posted an issue on the chewy gem github page, and I got some good feed back there that helped me eventually find a solution to my problem. I figured that it wouldn't hurt to also post it here for the greater good. Here are the specifics of my question.
I have recently switched from MySQL over to Postgres with multiple schemas, and am having trouble with rake chewy:reset:all
. It looks as though it is defaulting to the "public" schema, but I want to specify the schema. I am using the apartment gem, so I put this in one of my indexes:
Apartment::Tenant.switch!('tenant_name')
That fixed the rake problem temporarily, but it got me thinking bigger about elasticsearch and chewy and multi-tenancy in general. Does chewy have any sort of implementation of that? If not, do you have any recommendations?
I created a chewy monkey patch initializer:
# config/initializers/chewy_multi_tenancy.rb
module Chewy
class Index
def self.index_name(suggest = nil)
prefix = Apartment::Tenant.current
if suggest
@index_name = build_index_name(suggest, prefix: prefix)
else
@index_name = build_index_name(
name.sub(/Index\Z/, '').demodulize.underscore,
prefix: prefix
) if name
end
end
@index_name or raise UndefinedIndex
end
end
end
And a custom rake task:
# lib/tasks/elastic.rake
namespace :elastic do
desc "resets all indexes for a given tenant ('rake elastic:reset TENANT=tenant_name')"
task reset: :environment do
if ENV['TENANT'].nil?
puts "Uh oh! You didn't specify a tenant!\n"
puts "Example: rake elastic:reset TENANT=tenant_name"
exit
elsif !Apartment.tenant_names.include?(ENV['TENANT'])
puts "That tenant doesn't exist. Please choose from the following:\n"
puts Apartment.tenant_names
exit
else
Apartment::Tenant.switch!(ENV['TENANT'])
Rake::Task['chewy:reset:all'].invoke
end
end
end
Since I have a completely separate test cluster we don't need to prefix our indexes with "test", so I redefined prefix
with the current tenant name. As far as I can tell right now, chewy hits the index_name
method every time a specific index is called. It then grabs the correct users index for the current tenant.