Calling Ruby method from specific ancestors

Recently, I wanted to use attr_encrypted method from symmetric-encryption gem in one of the models in my Rails application.

Because of devise (which relies on attr_encrypted gem) being used in the codebase, whenever I used attr_encrypted in the model, I called method from attr_encrypted gem instead of symmetric-encryption. It was caused by higher position of AttrEncrypted module in the eigenclass’s included_modules:

> MyModel.superclass.included_modules
=> [AttrEncrypted::Adapters::ActiveRecord, AttrEncrypted, ..., SymmetricEncryption::ActiveRecord::AttrEncrypted::ClassMethods, ...]

Since SymmetricEncryption::ActiveRecord::AttrEncrypted is already injected, extending it in the model (or including it on MyModel.supperclass) again wouldn’t move it to the top of the list. To work around it, I decided to use an alternative solution based on an unbound method to execute a method from a given object in the context of that class:

SymmetricEncryption::ActiveRecord::AttrEncrypted.instance_method(:attr_encrypted).bind(self).call

To make it easier to use from the models, helper class method can be added to ApplicationRecord:

class ApplicationRecord
  def self.attr_encrypted_symmetrically(*args, **kwargs)
    SymmetricEncryption::ActiveRecord::AttrEncrypted::ClassMethods.instance_method(:attr_encrypted).bind(self).call(*args, **kwargs)
  end
end

Then:

class MyModel
  attr_encrypted_symmetrically :password
end