Hello guys!

I'd like to propose new feature for ActiveSupport Module's delegate method. 
I've actually implemented it already and i want your opinion on this 
matter. Recently during my work hours, i was writing enumerable 
proxy-object to encapsulate some business-logic and i wanted it to mimic 
Array functionally as much as possible, though behave in slightly different 
way.

I wanted to do it with composition, because i wholeheartedly agree with 
Steve Klabnik's article on 'subclassing vs composition' here:
http://words.steveklabnik.com/beware-subclassing-ruby-core-classes

Delegate method quickly came to my mind, though i had one concern: 
delegated methods on proxy object must return proxy object itself to enable 
chaining of filters and such.

I'll demonstrate it with example, let's look on standard delegation:

class ProxyContainer < Struct.new(:array)
   delegate :select!, to: :array
end

  >>> proxy = ProxyContainer.new(%w{a b c})
  => #<struct ProxyContainer array=["a", "b", "c"]>
  >>> proxy.select! { |el| el != 'a' }
  => ["b", "c"]

If we want to apply some business-logic filter and such, residing in proxy 
object, we must assign intermediate value to some variable, we cannot chain 
methods.

On the opposite side look at this delegation example with return_value_of 
in use:

class ProxyContainer < Struct.new(:brands)
   delegate :select!, to: :brands, return_value_of: :self

   def reject_unprofitable!
     # some business-logic here
   end

   def profitable
     # some business-logic here too
     @brands # profitable brands
   end

   def business_criteria
     # criteria logic
   end
end

Now we can do stuff like this:

  >>> proxy = ProxyContainer.new([#brand objects#])
  => #<struct ProxyContainer brands=[#brand objects#]>
  >>> proxy.select!(&:criteria).reject_unprofitable!
  => #<struct ProxyContainer brands=[#profitable brands#]>

If we want to use standard behaviour:

  >>> proxy.select!(&:criteria).profitable
  => [#profitable brands#]

It's kind of switching default focus in a favor of proxy, making instance 
variable returns explicit in user-made logic.

Look at how simple it looks and feels. It doesn't break backward 
compatibility and it will be easy to refactor, if it'll come to this(maybe 
it is, by the looks of github issues).

I've added test and implementations and squashed to this commit:
https://github.com/dredozubov/rails/commit/81940715a2137ae765419d338d5c1704b1e54d8b

I can open parallel PR on github if needed.
I'll be glad to update docs(or help to update them - my english isn't 
perfect), if you will approve this one.

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to rubyonrails-core+unsubscr...@googlegroups.com.
To post to this group, send email to rubyonrails-core@googlegroups.com.
Visit this group at http://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to