Including modules on singleton objects in Ruby
Zenchi‘s relational model has the following relationship:
User has_many memberships
membership is say, a Coinbase account. This model contains the email associated with this account, among other things of that nature.
Separately, we have a
Coinbase module, which has a static method
refresh_transactions(user) that updates a User’s Coinbase transactions.
This means a user has to have a Coinbase membership and utilize the
Coinbase module. When more services like Coinbase come into the picture, we will add a membership and module for each. Could be better.
My thinking - 'why can’t each membership have the same set of methods, defined differently?’
Solution: dynamically include modules based on the type of membership. This way, Coinbase memberships and Bitstamp memberships will have a different set of methods.
Like so -
class Membership < ActiveRecord::Base after_save :include_something def include_something class << self if name == 'Coinbase' include Coinbase elsif name == 'Bitstamp' include Bitstamp end end end end
What is happening here? Let’s give an example. Here are our modules:
module Coinbase def refresh_transactions # does some stuff end end module Bitstamp def refresh_transactions # does different stuff end end
And here is the execution example.
m = Membership.create(name: 'Coinbase', user_id: 1) m.refresh_transactions #- refreshes user 1's cb transactions # mm = Membership.create(name: 'Bitstamp', user_id: 1) m.refresh_transactions #- refreshes user 1's bs transactions
Going back to the model code -
class << self makes the
self receiver the instance of Membership calling this method. So
include Coinbase isn’t
Class.include Coinbase like you’re used to, it’s
instance.include Coinbase, in this case…
m. We dump all of the Coinbase’s methods into the single instance’s method pool.
I’m now realizing I just rediscovered OO.
EDIT: The shortcut to the following code is as so: