Home > Mobile >  Unable to extend ActiveRecord from within gem
Unable to extend ActiveRecord from within gem

Time:09-16

I'd like my gem to add a method to my AR classes that would enable some functionality:

class User < ApplicationRecord
  enable_my_uber_features :blah
end

For this, within my_uber_gem/lib/uber_gem.rb, I attempt the following:

# my_uber_gem/lib/uber_gem.rb

require "active_support"
# ...
require "uber/extensions"
# ...

ActiveSupport.on_load(:active_record) do

  class ActiveRecord::Base
    include Uber::Extensions
  end
end

In uber/extensions.rb I have:

# my_uber_gem/lib/uber/extensions.rb

require 'active_support/concern'
module Uber
    module Extensions
        extend ActiveSupport::Concern
        
        instance_methods do
            def foo
                p :bar
            end
        end

        class_methods do
            def enable_my_uber_features(value)
                p value
            end
        end
    end
end

Now I'd expect to see a blah in the console when instantiating an User, however I get an error:

[...] `method_missing': undefined method `enable_my_uber_features' for User:Class (NoMethodError)

I've tried including Uber::Extensions into ApplicationRecord instead of ActiveRecord::Base, no luck.

I've also tried extend Uber::Extensions, no luck.

I've also tried defining a module ClassMethods from within Uber::Extensions the extending/including, still no luck.

I've also followed this guy's guide by the letter: https://waynechu.cc/posts/405-how-to-extend-activerecord, still no luck.

Am I doing something wrong?

CodePudding user response:

The way I've done this is:

# in my_uber_gem/lib/active_record/base/activerecord_base.rb
require 'uber/extensions'
class ActiveRecord::Base
  include Uber::Extensions
  def baz
    p "got baz"
  end
end

# and in the my_uber_gem/lib/my_uber_gem.rb
module MyUberGem
  require_relative './active_record/base/activerecord_base.rb'
end

# and finally define the extension in my_uber_gem/lib/uber/extensions.rb
require 'active_support/concern'
class Uber
  module Extensions
    extend ActiveSupport::Concern
    def foobar(val)
      p val
    end
  end
end

# now you can do
User.first.foobar("qux") #=> "qux"
User.first.baz #=> "got baz"

CodePudding user response:

Turns out Rails was caching my local gem I was working on, and any changes I made to any gem files were only visible in a new app or after rebuilding the entire machine.

I was able to turn this off so it will reload the gem on every console reload:

  # config/environments/development.rb
  config.autoload_paths  = %W(#{config.root}/../my_uber_gem/lib)
  ActiveSupport::Dependencies.explicitly_unloadable_constants << 'MyUberGem'
  • Related