Overriding Model in Gem, Adding Callback and Methods

Overriding model in gem, adding callback and methods

Simply reopen the class:

module ReputationSystem
class Evaluation < ActiveRecord::Base
def my_method_here
puts "Yey!"
end
end
end

You can put this file in config/initializers/my_monkey_patch.rb or in lib/my_monkey_patch.rb, but the later must be loaded into your code.

How to override model from the doorkeeper gem

This is how I'm doing right now, still developing anyway so I'll update if I'll find issues.

I'm doing this using ActiveRecord, maybe for Mongoid/Mongomapper some changes need to be done.

Luckily Doorkeeper::Application has all the configuration to set the correct table name so you don't have to bother about that.

With this in mind you can just add app/models/application.rb like this:

class Application < Doorkeeper::Application
require 'identicon'
before_create :generate_identicon

def generate_identicon
self.identicon = Identicon.data_url_for name, 128, [255, 255, 255]
end
end

And you're done.

I'm using this to customize Doorkeepe::Application with RailsAdmin (just to add some keyword if someone lands here)

Overwriting a dependency gem class which inherits from a parent class

No, you can't actually change the parent class without basically rewriting the subclass. If you only have two methods in each class that's probably fine, but Ruby classes use single-inheritance, so you can't re-assign a subclass to a different superclass without redefining it. You can, however, do any of the following:

  1. Re-open the class and redefine its methods.
  2. Prepend a module to redefine the behavior of existing methods.
  3. Add or modify methods for the singleton class, or on a singleton instance of that class.
  4. If your class is inheriting from Delegator, you can change the delegate class with #__setobj__.

Since you haven't really defined a use case, it's hard to tell which method would be best for you. Once the parent class is defined, though, it stays defined, so you'll have to do whatever you're trying to do another way.

Inherit controller class from gem

After two days of troubleshooting I realized their Gemspec was including an old version of rails that did not contain the method they were calling..

I let them know and bumped my version from 4.2.5 to 4.2.6 and now it works.. frustrating but solved.. thanks everyone for your support!

If anyone else comes across this, in order to use the Shopify App gem Webhooks controller you will need to be running Rails 4.2.6.

Using method callbacks in plain Ruby class

A naive implementation would be;

module Callbacks

def self.extended(base)
base.send(:include, InstanceMethods)
end

def overridden_methods
@overridden_methods ||= []
end

def callbacks
@callbacks ||= Hash.new { |hash, key| hash[key] = [] }
end

def method_added(method_name)
return if should_override?(method_name)

overridden_methods << method_name
original_method_name = "original_#{method_name}"
alias_method(original_method_name, method_name)

define_method(method_name) do |*args|
run_callbacks_for(method_name)
send(original_method_name, *args)
end
end

def should_override?(method_name)
overridden_methods.include?(method_name) || method_name =~ /original_/
end

def before_run(method_name, callback)
callbacks[method_name] << callback
end

module InstanceMethods
def run_callbacks_for(method_name)
self.class.callbacks[method_name].to_a.each do |callback|
send(callback)
end
end
end
end

class Foo
extend Callbacks

before_run :bar, :zoo

def bar
puts 'bar'
end

def zoo
puts 'This runs everytime you call `bar`'
end

end

Foo.new.bar #=> This runs everytime you call `bar`
#=> bar

The tricky point in this implementation is, method_added. Whenever a method gets bind, method_added method gets called by ruby with the name of the method. Inside of this method, what I am doing is just name mangling and overriding the original method with the new one which first runs the callbacks then calls the original method.

Note that, this implementation neither supports block callbacks nor callbacks for super class methods. Both of them could be implemented easily though.



Related Topics



Leave a reply



Submit