All Projects → stevenharman → dumb_delegator

stevenharman / dumb_delegator

Licence: MIT License
Delegator and SimpleDelegator in Ruby's stdlib are useful, but they pull in most of Kernel. This is not appropriate for many uses; for instance, delegation to Rails models.

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to dumb delegator

Design-Patterns
A collection of popular design patterns with video and text explanations
Stars: ✭ 159 (+156.45%)
Mutual labels:  design-patterns
design-pattern-examples-in-python
UML model and code examples of design patterns for Python. The model is created with Astah.
Stars: ✭ 27 (-56.45%)
Mutual labels:  design-patterns
vala-design-patterns-for-humans
A Vala version of "Design Patterns for Humans"
Stars: ✭ 15 (-75.81%)
Mutual labels:  design-patterns
sherpa 41
Simple browser engine.
Stars: ✭ 31 (-50%)
Mutual labels:  design-patterns
here-we-go
Contains hundreds of samples for learning Go.
Stars: ✭ 93 (+50%)
Mutual labels:  design-patterns
java-design-patterns
设计模式专题,共 23 种设计模式。GOF design patterns,implement of Java。
Stars: ✭ 32 (-48.39%)
Mutual labels:  design-patterns
objproxies
Proxies and wrappers for ordinary Python objects
Stars: ✭ 18 (-70.97%)
Mutual labels:  design-patterns
TestableDesignExample
Sample App to learn a testable design (Smalltalk flavored MVC)
Stars: ✭ 80 (+29.03%)
Mutual labels:  design-patterns
php-design-patterns
Learn how to implement the most important Design Patterns into your PHP application. This project uses PHP 8.1. it has examples for each Pattern and an Article explaining how to use them step by step, their advantages, and disadvantages.
Stars: ✭ 151 (+143.55%)
Mutual labels:  design-patterns
ezyfox
Java library supports for reflection, generic, annotations parsing, bean management and object binding
Stars: ✭ 14 (-77.42%)
Mutual labels:  design-patterns
OOP-Design-Patterns
MET CS665 - OOP Design Patterns Code Examples
Stars: ✭ 74 (+19.35%)
Mutual labels:  design-patterns
design-patterns-php7
Design Patterns com PHP 7: Desenvolva com as melhores soluções. Repositório com os exemplos de código do livro. Repository with the code examples in the book.
Stars: ✭ 51 (-17.74%)
Mutual labels:  design-patterns
enterprise-applications-patterns
Collection of enterprise application patterns
Stars: ✭ 17 (-72.58%)
Mutual labels:  design-patterns
Study-Notes
🤔💡 😃 😎 Algorithms, Data Structures, Design Patterns
Stars: ✭ 56 (-9.68%)
Mutual labels:  design-patterns
design-patterns-for-humans-cn
Design patterns for humans 中文版 - 对设计模式超简单的解释
Stars: ✭ 2,432 (+3822.58%)
Mutual labels:  design-patterns
spark-design-system
Spark Design System
Stars: ✭ 101 (+62.9%)
Mutual labels:  design-patterns
design-patterns
Simple examples of Design Patterns with PHP Examples
Stars: ✭ 75 (+20.97%)
Mutual labels:  design-patterns
DataStructures Algorithms Java
Collection of data structures and algorithms challenges that I've solved. 💤
Stars: ✭ 12 (-80.65%)
Mutual labels:  design-patterns
DotNETCarRental
Daily car rental simulation with ASP.NET.
Stars: ✭ 13 (-79.03%)
Mutual labels:  design-patterns
mvc-tree
🌳 A chronological visualization of the family of MVC patterns.
Stars: ✭ 40 (-35.48%)
Mutual labels:  design-patterns

DumbDelegator

Gem Version CI Maintainability Test Coverage

Ruby provides the delegate standard library. However, we found that it is not appropriate for cases that require nearly every call to be proxied.

For instance, Rails uses #class and #instance_of? to introspect on Model classes when generating forms and URL helpers. These methods are not forwarded when using Delegator or SimpleDelegator.

require "delegate"

class MyAwesomeClass
  # ...
end

o = MyAwesomeClass.new
d = SimpleDelegator.new(o)

d.class                #=> SimpleDelegator
d.is_a? MyAwesomeClass #=> false

DumbDelegator, on the other hand, forwards almost ALL THE THINGS:

require "dumb_delegator"

class MyAwesomeClass
  # ...
end

o = MyAwesomeClass.new
d = DumbDelegator.new(o)

d.class                #=> MyAwesomeClass
d.is_a? MyAwesomeClass #=> true

Installation

Add this line to your Gemfile:

gem "dumb_delegator"

And then install:

$ bundle

Or install it yourself:

$ gem install dumb_delegator

Versioning

This project adheres to Semantic Versioning.

Version 0.8.x

The 0.8.0 release was downloaded 1.2MM times before the 1.0.0 work began. Which is great! 🎉 But, we wanted to clean up some cruft, fix a few small things, and improve ergonomics. And we wanted to do all of that while, hopefully, not breaking existing usage.

To that end, 1.0.0 dropped support for all EoL'd Rubies and only officially supported Ruby 2.4 - 2.7 when it was released. However, most older Rubies, should still work. Maybe… Shmaybe? Except for Ruby 1.9, which probably does not work with DumbDelegator > 1.0.0. If you're on an EoL'd Ruby, please try the 0.8.x versions of this gem.

Usage

DumbDelegator's API and usage patters were inspired by Ruby stdlib's SimpleDelegator. So the usage and ergonomics are quite similar.

require "dumb_delegator"

class Coffee
  def cost
    2
  end

  def origin
    "Colombia"
  end
end

class Milk < DumbDelegator
  def cost
    super + 0.4
  end
end

class Sugar < DumbDelegator
  def cost
    super + 0.2
  end
end

coffee = Coffee.new

cup_o_coffee = Sugar.new(Milk.new(coffee))
cup_o_coffee.origin        #=> Colombia
cup_o_coffee.cost          #=> 2.6

# Introspection
cup_o_coffee.class         #=> Coffee
cup_o_coffee.__getobj__    #=> #<Coffee:0x00007fabed1d6910>
cup_o_coffee.inspect       #=> "#<Sugar:70188197507600 obj: #<Milk:70188197507620 obj: #<Coffee:0x00007fabed1d6910>>>"
cup_o_coffee.is_a?(Coffee) #=> true
cup_o_coffee.is_a?(Milk)   #=> true
cup_o_coffee.is_a?(Sugar)  #=> true

Rails Model Decorator

There are many decorator implementations in Ruby. One of the simplest is "SimpleDelegator + super + __getobj__," but it has the drawback of confusing Rails. It is necessary to redefine #class, at a minimum. If you're relying on Rails' URL Helpers with a delegated object, you also need to redefine #instance_of?. We've also observed the need to redefine other Rails-y methods to get various bits of 🧙 Rails Magic 🧙 to work as expected.

With DumbDelegator, there's not a need for redefining these things because nearly every possible method is delegated.

Optional case statement support

Instances of DumbDelegator will delegate #=== out of the box. Meaning an instance can be used in a case statement so long as the when clauses rely on instance comparison. For example, when using a case with a regular expression, range, etc...

It's also common to use Class/Module in the where clauses. In such usage, it's the Class/Module's ::=== method that gets called, rather than the #=== method on the DumbDelegator instance. That means we need to override each Class/Module's ::=== method, or even monkey-patch ::Module::===.

DumbDelegator ships with an optional extension to override a Class/Module's ::=== method. But you need to extend each Class/Module you use in a where clause.

def try_a_case(thing)
  case thing
  when MyAwesomeClass
    "thing is a MyAwesomeClass."
  when DumbDelegator
    "thing is a DumbDelegator."
  else
    "Bad. This is bad."
  end
end

target = MyAwesomeClass.new
dummy = DumbDelegator.new(target)

try_a_case(dummy) #=> thing is a DumbDelegator.

MyAwesomeClass.extend(DumbDelegator::TripleEqualExt)

try_a_case(dummy) #=> thing is a MyAwesomeClass.

Overriding Module::===

If necessary, you could also override the base Module::===, though that's pretty invasive.

🐲 There be dragons! 🐉

::Module.extend(DumbDelegator::TripleEqualExt)

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Contribution Ideas/Needs

  1. Ruby 1.8 support (use the blankslate gem?)
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].