Override a method inside a gem from another gem

Ok, I have a gem rail I'm working on, and I want it to override a specific method in chains.

The method I want to override is: Sprockets :: Base.digest so that I can print the fingerprint from my version of gem when compiling the application.

How can i do this?

In my gem, I create the lib / sprockets / base.rb file and place the following code:

 class Sprockets :: Base                                                                                                                                                                                                                                                           
   def digest
     @digest = digest_class.new.update (MyGem :: VERSION)
     @ digest.dup
   end
 end

When I run bundle exec rake assets:precompile , I get:

undefined method 'logger=' for #<Sprockets::Environment:0x1315b040>

It seems to me that the whole class is redefined in some way (this will lose this and other methods) instead of just redefining one method.

If I include this piece of code directly in the rakefile of an application that uses both stones, everything works fine.

+3
override ruby ruby-on-rails ruby-on-rails-3 gem
Jan 05 '12 at 1:22
source share
2 answers

It is not possible to override the entire Ruby class this way, but I think it is possible to prevent the loading of the original class ... if it uses autoload. I was curious, so I checked https://github.com/sstephenson/sprockets/blob/master/lib/sprockets.rb and yes, Sprockets uses autoload.

 autoload :Base, "sprockets/base" 

It is important to note that this does not load code. It simply tells Ruby that if / when an undefined constant called "Sprockets :: Base" ever occurs, loads it from the specified file. The patch defines Sprockets :: Base before it is ever called anywhere, thereby preventing the source file from loading.

When you transferred the patch to Rakefile, something in Rails already referred to Sprockets :: Base, loading the source code. Then your patch has been applied from top to bottom.

I never used autoload, so I'm not sure how such cases should be handled. I am sure this will work:

 Sprockets::Base class Sprockets::Base def digest ... 

When referencing a class first, you must force Ruby to load the source class. Then you can safely get down to redefining one of your methods.

+6
Jan 05 '12 at 4:01
source share

Well, I correctly answered your answer, but it really led me to clarify the problem.

In any case, the rails application requires my base file, not the one in the stone itself. This is what you said. However, the reason this is happening was apparently caused by the path itself. The file path was basically the same as with the gem (lib / sprockets / base.rb).

Moving this file to my namespace "lib / my_gem instead of lib / sprockets" and renaming it to sprockets_base.rb fixed the problem! Strange, huh?

In other words, I am trying to maintain the directory structure in fact, it seems, confused Rails, thinking that it is the stone itself or something like that.

+1
Jan 05 2018-12-12T00:
source share



All Articles