Reputation: 1285
Our application is a Saas for the hospital, is deployed on one production server (same code with linux+nginx+puma) for all our clients. By default, there are three of them: test, development and production. But in our case, we have 10 environments config files point to 10 clients config file in folder 'config/environments/'. And we give hospitals name to environment file, such as
config/environments/hospital1.rb
config/environments/hospital2.rb
config/environments/hospital3.rb
...
There are several features paid is developed with engine
.
Now imagine that hospital1 paid for feature1. How to active feature1 only for hospital1 ? I am currently doing this in Gemfile
group :hospital1 do
gem 'feature1', path to ....
end
Question: Is this a good way to replace production environment to client-specific environment and be able to Enable/Disable a gem in GEMFILE ?
Any suggestion is welcome!
Upvotes: 3
Views: 162
Reputation: 18444
Approach with environment per customer does not scale well. Gemfile
is definitely not a place to keep client's settings. Also it's harder to test.
If you need strong separation (separate db, workers etc.) - I'd still go with one production
environment:
hospital1:
name: Imaginary Medical Center
address: Nowhere st. 0
features:
cool_notifications: true
feature2: false
hospital2:
name: ObfuscatedView Commutinu Hospital
features:
feature1: false
later this can evolve into an administrative database
HOSPITAL_NAME=hospital1 rails server -e production
), and make a singleton object that loads that config upon callingrequire: false
and you can only load them in application.rb (right after Bundler.require
) if corresponding feature is enabledAlso have a look at apartment gem, if you can allow some resource sharing (like web workers). You'll have to add multidomain support to your app and feature toggles, but it'll be even easier to handle growing client number (and save server resources, most probably none of your clients produce high sustained load)
Upvotes: 0
Reputation: 15985
This is really bad approach.
Basically you are trying to do multitanancy but in very odd and uncontrolled way.
It's an architectural decision and it cannot fit in StackOverflow answer and many take a whole book to explain it.
Take a look at https://rubygarage.org/blog/three-database-architectures-for-a-multi-tenant-rails-based-saas-app to get some perspective.
Basically feature enable/disable should be done based on rules which should easily be managed via some admin panel at the least.
Upvotes: 1
Reputation: 116
That sounds like a bad idea.
You're "mixing oranges and sofas" here. Environments and clients have different semantics.
What you have is either different instances of the same app deployed on different servers(and then client-specific stuff should come from environment variables), or if it is a single deployment(looks like it is your case), then client-specific setting should be stored in the database.
As for limiting access to paid features, you should look into solution like pundit to do that. Gemfile
is definitely not the right place for your business-logic!
Upvotes: 2
Reputation: 2488
Personally, I prefer to think of environment as technical-level thing, not application logic thing. Therefore I'd try to keep as few environments as possible. If you want to have conditional statements in Gemfile
perhaps it's better to use environment variables? Something like
if ENV['FEATURE_1_ENABLED']
gem 'feature1', path to ....
end
You could even automate managing of these variables by having a .env
file per hospital and load apropriate one with Dotenv.load
.
Upvotes: 1