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:
- Re-open the class and redefine its methods.
- Prepend a module to redefine the behavior of existing methods.
- Add or modify methods for the singleton class, or on a singleton instance of that class.
- 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
Ruby Defining Operator Procedure
Rails Format Validation -- Alphanumeric, But Not Purely Numeric
Ruby Installation (2.2.2) Fails in MACos Big Sur
Ruby's Argv Can Be Empty on Windows Depending on a Way to Run Script
When to Use Association Extensions VS Named Scopes
Ruby: Overriding the Puts Method
What Regex How to Use to Get the Domain Name from a Url in Ruby
Problem Installing Ruby 1.9.2 on MAC Os Lion
If 'Self' Is Always the Implied Receiver in Ruby, Why Doesn't 'Self.Puts' Work
Rails Form Object with Reform-Rails with Collections Not Working or Validating
How to Compare Private Attributes in Ruby
How to Specify a Regex Character Range That Will Work in European Languages Other Than English
Generating a Race Condition with Mri
Single Quote String String Interpolation