Git Product home page Git Product logo

equalizer's Introduction

equalizer

Module to define equality, equivalence and inspection methods

Gem Version Build Status Mutant Standard Yardstick

Examples

class GeoLocation
  include Equalizer.new(:latitude, :longitude)

  attr_reader :latitude, :longitude

  def initialize(latitude, longitude)
    @latitude, @longitude = latitude, longitude
  end
end

point_a = GeoLocation.new(1, 2)
point_b = GeoLocation.new(1, 2)
point_c = GeoLocation.new(2, 2)

point_a.inspect    # => "#<GeoLocation latitude=1 longitude=2>"

point_a == point_b           # => true
point_a.hash == point_b.hash # => true
point_a.eql?(point_b)        # => true
point_a.equal?(point_b)      # => false

point_a == point_c           # => false
point_a.hash == point_c.hash # => false
point_a.eql?(point_c)        # => false
point_a.equal?(point_c)      # => false

Supported Ruby Versions

This library aims to support and is tested against the following Ruby implementations:

  • Ruby 3.1
  • Ruby 3.2
  • Ruby 3.3

If something doesn't work on one of these versions, it's a bug.

This library may inadvertently work (or seem to work) on other Ruby versions or implementations, however support will only be provided for the implementations listed above.

If you would like this library to support another Ruby version or implementation, you may volunteer to be a maintainer. Being a maintainer entails making sure all tests run and pass on that implementation. When something breaks on your implementation, you will be responsible for providing patches in a timely fashion. If critical issues for a particular implementation exist at the time of a major release, support for that Ruby version may be dropped.

Credits

Contributing

See CONTRIBUTING.md for details.

Copyright

Copyright © 2009-2024 Dan Kubb. See LICENSE for details.

equalizer's People

Contributors

ch1c0t avatar craiglittle avatar dkubb avatar jsuchal avatar mbj avatar myronmarston avatar sferik avatar snusnu avatar solnic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

equalizer's Issues

Do not freeze during .new (Adamantium)

The Ruby convention is for Class and Module instances to be open. Immutable Equalizer instances breaks this convention.

Virtus::ValueObject.attribute is an example where an Equalizer instance can/should be mutable.

Since all the attributes of an Equalizer can be assigned in the constructor, I think it remains elegant to put the burden of immutability on the user:

class MyThing
  include IceNine.deep_freeze(Equalizer.new(:the, :keys))
end

extended objects do not work like objects of module included classes

Hi,

Currently equalizer only triggers when include'ed into a Module, I have a use case that fails with this assumption, here it is.

I only want the equalizer functionnalities for some objects, not all object of a class, so I define the equalizer like this:

  GeoLocationEqualizer = Equalizer.new(:latitude, :longitude)

The class like that:

  class GeoLocation
    attr_reader :latitude, :longitude

    def initialize(latitude, longitude)
      @latitude, @longitude = latitude, longitude
    end
  end

And the code using them:

  restaurants = get_locations_from('http://example.com/paris/restaurants')
  cafes = get_locations_from('http://example.com/paris/cafes')

  # I'm interested in comparing location only for those objects, extend them
  restaurants.each { |restaurant| restaurant.extend(GeoLocationEqualizer) }
  cafes.each { |cafe| cafe.extend(GeoLocationEqualizer) }

  # I want to know which cafes are on the same location as restaurants
  # (Array#& uses eql? and hash)
  matching = restaurants & cafes

In the current code, the Methods module is not mixed in when extend'ing objects.
For that we have to add the extend_object hook like this:

  def extend_object(obj)
    obj.extend Methods
    super
  end

May this be added to master? Should I submit a PR?

Regards

Wrong devtools version in Gemfile

➜  equalizer git:(master) bundle
Updating https://github.com/mbj/devtools.git
Fetching gem metadata from https://rubygems.org/.........
Fetching version metadata from https://rubygems.org/..
Could not find gem 'devtools (= 0.0.2) ruby' in https://github.com/mbj/devtools.git (at master).
Source contains 'devtools' at: 0.1.2

Equalizer causes “Undocumentable mixin” warning in YARD

When using Equalizer in projects that use YARD for documentation, YARD raises a YARD::Parser::UndocumentableError on every line that mixes-in Equalizer.

I’m not sure exactly how to solve this problem. Maybe I should just silence the warnings in YARD or maybe Equalizer should change its interface to mix-in a static module and then use class methods to define which attributes to use for equality. For example:

class GeoLocation
  include Equalizer
  attr_reader :latitude, :longitude
  equalize :latitude, :longitude

  def initialize(latitude, longitude)
    @latitude, @longitude = latitude, longitude
  end
end

I’m interested to have some discussion around this issue.

/cc @lsegal

Change `#==` dependency from `#coerce` to `#equalizer_coerce`

I have an object which defines a #coerce instance method as part of its public API. I didn't realize until recently that this breaks #== for this object and all of the objects that own it until today.

I understand after talking to @dkubb that this is a weak convention in ruby, but it might make sense to deprecate the use of #coerce and instead depend on a method that is less likely to naturally collide with unrelated method names that are not meant for equalizer

Equality with Object.new

Hi,

I suppose this error is not intentional behavior?

require 'equalizer'

class GeoLocation
  include Equalizer.new(:latitude, :longitude)

  attr_reader :latitude, :longitude

  def initialize(latitude, longitude)
    @latitude, @longitude = latitude, longitude
  end
end

point_a = GeoLocation.new(1, 2)
point_b = GeoLocation.new(1, 2)

point_a == point_b # true
point_a == Object.new # NoMethodError: undefined method `latitude' for #<Object:0x00000001c91728>

BTW. Awesome trick with the module subclassing and instantiation. I've never imagined this is possible and used my own monkey patch. https://gist.github.com/4252597

Support for inheritance?

What if we have Foo that includes an equalizer and then have Bar < Foo that includes another one? Do you think we should support that automatically? As in, should it "merge" those equalizers together in the inherited hook?

Private `#hash` method is slow

Heya, thanks for equalizer!

Was debugging a performance issue today and noticed that ~25% of the request time was taken up by repeated calls to equalizer's #hash method when I was using an equalized value object as a hash key. It also appears that ~60% of that ~25% was calling #to_proc on method(:send), so caching the proc'ed send in a constant or something may help. As a comparison, switching to using a stringified version of my value object as the hash key was relatively free... i.e. subsequent requests sped up by ~25%.

Not a deal breaker, just a heads-up. Attached a screenshot of the flamegraph in case it helps.

screenshot from 2015-12-01 17 42 59

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.