Pull some configuration variables from the DB to set dynamically in Rails environment?

673 Views Asked by At

Is it possible to set some configuration variables in production.rb dynamically using values from the database?

I'm building a multi-tenant app and each tenant has some environment specific information that needs to be set dynamically.

For example:

// production.rb
config.action_mailer.default_url_options  = { :host => current_tenant.domain }

The current_tenant is a helper method is defined in ApplicationHelper so can't be accessed in production.rb

Here is current_tenant:

// application_helper.rb
def current_tenant
  @current_tenant ||= Tenant.find_by(domain: Apartment::Tenant.current)
end

If not, is it possible to dynamically create secrets.yml using DB data? Since then I would be able to use ENV in production.rb

2

There are 2 best solutions below

5
On

Maybe you can try this instead: Create a helper method for your emails:

def build_tenant_url(route_name, *args)
  opts = args.extract_options!
  opts.merge!(host: @tenant ? @tenant.domain : your_domain)
  #Here you can merge other options if you need to pass a token etc
  Rails.application.routes_url_helpers.send(:"#{route_name}_url", *args, opts)
end

In your mailer, define the @tenant

Then in your email view use it

= link_to 'Edit', build_tenant_url(:edit_tenant, @tenant) 
0
On

This setup runs when the app starts up, so if you want an option to be driven by some variable, that variable will need to be available to the Ruby code that runs at startup. There's various ways this could be done

  • the script (or whatever) which starts your rails server passes through a parameter
  • a value is written into a text file by some other process and read out again by the startup script
  • same again but with an environment variable

For example, if you were giving each tenant (group of users) their own subdomain on your app, then the subdomain name could be used as a key for the startup code to read the database and pull out some details for that tenant. This subdomain would then be passed through to the app when you spin it up.

EDIT - having said all this, i'm not sure if it's necessary for you to change the startup config at all. Can't you just look up the appropriate domain name whenever you send an email, rather than changing the default set in the config?