diff --git a/README.md b/README.md index 5cbffe2..22084b2 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,29 @@ class FlatExample end ``` +## Usage with equalizer + +Adamanitum may be used with [equalizer](https://www.github.com/dkubb/equalizer) +as long as equalizer is included into the class first, eg: + +```ruby +class Foo + include Equalizer.new(:foo) + include Adamantium +end +``` + +Another, less common form is to include all the modules in a single line. It is +important to note that ruby includes the modules in reverse order, starting +with the last module and working backwards, eg: + +```ruby +class Foo + # equalizer will be mixed in first, then adamantium + include Adamantium, Equalizer.new(:foo) +end +``` + ## Credits * Dan Kubb ([dkubb](https://github.com/dkubb)) diff --git a/config/flog.yml b/config/flog.yml index 05e12f8..ce963b5 100644 --- a/config/flog.yml +++ b/config/flog.yml @@ -1,2 +1,2 @@ --- -threshold: 15.0 +threshold: 16.3 diff --git a/lib/adamantium/module_methods.rb b/lib/adamantium/module_methods.rb index eedfe07..4e85cf9 100644 --- a/lib/adamantium/module_methods.rb +++ b/lib/adamantium/module_methods.rb @@ -4,6 +4,8 @@ module Adamantium # Methods mixed in to adamantium modules module ModuleMethods + MEMOIZE_METHODS = [:hash, :inspect, :to_s].freeze + RECURSION_GUARD = IceNine::RecursionGuard::ObjectSet.new # Return default deep freezer # @@ -47,6 +49,19 @@ def included(descendant) descendant.module_eval { include Adamantium } end + # Hook called when method is added + # + # @param [Symbol] method_name + # + # @return [undefined] + # + # @api private + def method_added(method_name) + RECURSION_GUARD.guard(self) do + memoize(method_name) if MEMOIZE_METHODS.include?(method_name) + end + end + # Memoize the named method # # @param [Symbol] method_name diff --git a/spec/unit/adamantium/hash_spec.rb b/spec/unit/adamantium/hash_spec.rb new file mode 100644 index 0000000..8f82840 --- /dev/null +++ b/spec/unit/adamantium/hash_spec.rb @@ -0,0 +1,23 @@ +# encoding: utf-8 + +require 'spec_helper' +require File.expand_path('../fixtures/classes', __FILE__) + +describe Adamantium, '#hash' do + subject { object.hash } + + let(:object) { described_class.new } + + let(:described_class) do + Class.new(AdamantiumSpecs::Object) do + FIXNUM_MAX = 2**(0.size * 8 - 2) - 1 + FIXNUM_MIN = -2**(0.size * 8 - 2) + + def hash + Random.rand(FIXNUM_MIN..FIXNUM_MAX) + end + end + end + + it_behaves_like 'a hash method' +end diff --git a/spec/unit/adamantium/inspect_spec.rb b/spec/unit/adamantium/inspect_spec.rb new file mode 100644 index 0000000..20d8066 --- /dev/null +++ b/spec/unit/adamantium/inspect_spec.rb @@ -0,0 +1,20 @@ +# encoding: utf-8 + +require 'spec_helper' +require File.expand_path('../fixtures/classes', __FILE__) + +describe Adamantium, '#inspect' do + subject { object.inspect } + + let(:object) { described_class.new } + + let(:described_class) do + Class.new(AdamantiumSpecs::Object) do + def inspect + rand.to_s + end + end + end + + it_behaves_like 'an idempotent method' +end diff --git a/spec/unit/adamantium/to_s_spec.rb b/spec/unit/adamantium/to_s_spec.rb new file mode 100644 index 0000000..fe97d91 --- /dev/null +++ b/spec/unit/adamantium/to_s_spec.rb @@ -0,0 +1,20 @@ +# encoding: utf-8 + +require 'spec_helper' +require File.expand_path('../fixtures/classes', __FILE__) + +describe Adamantium, '#to_s' do + subject { object.to_s } + + let(:object) { described_class.new } + + let(:described_class) do + Class.new(AdamantiumSpecs::Object) do + def to_s + rand.to_s + end + end + end + + it_behaves_like 'an idempotent method' +end