Created
September 12, 2019 12:10
-
-
Save matheussilvasantos/a42fd23136162a16d4bb89839c4ad6b2 to your computer and use it in GitHub Desktop.
Rest
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module REST | |
def self.OAuth(client) | |
REST::OAuth.new(client) | |
end | |
class OAuth < Module | |
def initialize(client) | |
@client = client | |
freeze | |
end | |
private | |
def included(descendant) | |
super | |
descendant.send(:include, Methods) | |
end | |
def define_methods | |
define_cmp_method | |
define_hash_method | |
define_inspect_method if inspect | |
end | |
# Define an #cmp? method based on the instance's values identified by #keys | |
# | |
# @return [undefined] | |
# | |
# @api private | |
def define_cmp_method | |
keys = @keys | |
define_method(:cmp?) do |comparator, other| | |
keys.all? do |key| | |
__send__(key).public_send(comparator, other.__send__(key)) | |
end | |
end | |
private :cmp? | |
end | |
# Define a #hash method based on the instance's values identified by #keys | |
# | |
# @return [undefined] | |
# | |
# @api private | |
def define_hash_method | |
keys = @keys | |
define_method(:hash) do | | | |
keys.map(&method(:send)).push(self.class).hash | |
end | |
end | |
# Define an inspect method that reports the values of the instance's keys | |
# | |
# @return [undefined] | |
# | |
# @api private | |
def define_inspect_method | |
keys = @keys | |
define_method(:inspect) do | | | |
klass = self.class | |
name = klass.name || klass.inspect | |
"#<#{name}#{keys.map { |key| " #{key}=#{__send__(key).inspect}" }.join}>" | |
end | |
end | |
# The comparison methods | |
module Methods | |
# Compare the object with other object for equality | |
# | |
# @example | |
# object.eql?(other) # => true or false | |
# | |
# @param [Object] other | |
# the other object to compare with | |
# | |
# @return [Boolean] | |
# | |
# @api public | |
def eql?(other) | |
instance_of?(other.class) && cmp?(__method__, other) | |
end | |
# Compare the object with other object for equivalency | |
# | |
# @example | |
# object == other # => true or false | |
# | |
# @param [Object] other | |
# the other object to compare with | |
# | |
# @return [Boolean] | |
# | |
# @api public | |
def ==(other) | |
other.is_a?(self.class) && cmp?(__method__, other) | |
end | |
end # module Methods | |
end # class Equalizer | |
end |
PS: I think it would be possible to build a facilitator that would get you rid of all this boilerplate (the define_methods
, the base.send :include, Methods
, and possibly even the define_XXX_method
s...
Sounds like a nice weekend challenge
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've warped your example a little bit but this should be understandable.
I added a few comments on the code to explain the need for certain things