We have a Rails app hosted on Heroku and i need to set up some analytics pages for our marketing guy. This seems to be the typical use case for a Heroku follow database
The 2 databases will share the same model classes, i want only some action to query the replicated database.
What is the preferred way to handle this situation in my app ?
ActiveRecord::Base documentation talks about class specific connection :
You can also set a class-specific connection. For example, if Course is an ActiveRecord::Base, but resides in a different database, you can just say Course.establish_connection and Course and all of its subclasses will use this connection instead.
Should i subclass all my model classes to specify connection to a secondary database ? (will it even work ?)
I also found this gem but it seems not maintained anymore.... magic_multi_connections gem ?
So... I like this solution:
module Analytics
class Base < ActiveRecord::Base
self.abstract_class = true
establish_connection ENV['ANALYTICS_DATABASE_URL']
end
class User < Base; end
class Product < Base; end
end
Now you have models that all connect to your analytics database (the follower).
If you need to share scopes or methods between your analytics app and your normal app, you could put the shared code in a mixin, and then just include that in either of your Analytics or normal models.
Alternatively you can just call .establish_connection
on the models you need to use for analytics in the controller prior to using them for analytics, but I don't know if that will muck up your connection for other normal web requests, requiring you to set it back to your normal database connection on the next request...
UPDATE: Another idea just struck me:
class UserBase < ActiveRecord::Base
self.abstract_class = true
# all your user model code goes here
end
class User < UserBase
establish_connection(Rails.env) # connect to your normal database
end
class AnalyticsUser < UserBase
self.table_name = 'users'
establish_connection(ENV['ANALYTICS_DATABASE_URL'])
end
This allows you to share all the code between your models whether they are for analytics or normal web requests, but set a different connection depending on the model name.
Also, as a sidenote, if you don't want to set up a follower in your development environment, just set ENV['ANALYTICS_DATABASE_URL'] in your development.rb:
ENV['ANALYTICS_DATABASE_URL'] ||= 'postgres://localhost/myapp_development'
And obviously, on Heroku, you'll need to rename or set the config var for your ANALYTICS_DATABASE_URL to whatever the DATABASE_URL for your follower is.
To better answer this question : Heroku has now posted an "official" way of dealing with this situation using the Octopus gem :
https://devcenter.heroku.com/articles/distributing-reads-to-followers-with-octopus
With this gem it's possible to create either a fully replicated model, or execute only a block on the follower :
Octopus.using(:slave_two) do
User.create(:name => "Mike")
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With