Overridding A Method Via A Mixin

Hi Everyone,

I believe one can add methods to a class by including a module but not override existing methods. Indeed Dr Nic said as much here:

http://ruby.tie-rack.org/6/safely-overriding-method_missing-in-a-class-that-already-has-it/#comment-7

Here's some code that demonstrates this.

class Foo
   def answer
     42
   end
end

module Bar
   def answer
     "What was the question?"
   end

   def to_s
     "bar"
   end
end

Foo.send :include, Bar
f = Foo.new
f.answer # => 42, not "What was the question?"
f.to_s # => "bar", not "#<Foo:0x731248>"

Why aren't existing methods overridden? And where could I have looked to find out the answer for myself (perhaps somewhere in Ruby's source?)?

Thanks and regards,
Andy

···

-------
http://airbladesoftware.com

Because of the position in the inheritance hierarchy:

irb(main):001:0> module Bar;end
=> nil
irb(main):002:0> class Foo
irb(main):003:1> include Bar
irb(main):004:1> end
=> Foo
irb(main):005:0> Foo.ancestors
=> [Foo, Bar, Object, Kernel]

Methods defined in Foo are always found before their counterparts in included modules. Consequently you can override super class methods with a module.

Kind regards

  robert

···

On 15.01.2008 18:32, Andrew Stewart wrote:

Hi Everyone,

I believe one can add methods to a class by including a module but not override existing methods. Indeed Dr Nic said as much here:

http://ruby.tie-rack.org/6/safely-overriding-method_missing-in-a- class-that-already-has-it/#comment-7

Here's some code that demonstrates this.

class Foo
   def answer
     42
   end
end

module Bar
   def answer
     "What was the question?"
   end

   def to_s
     "bar"
   end
end

Foo.send :include, Bar
f = Foo.new
f.answer # => 42, not "What was the question?"
f.to_s # => "bar", not "#<Foo:0x731248>"

Why aren't existing methods overridden? And where could I have looked to find out the answer for myself (perhaps somewhere in Ruby's source?)?

hi andrew!

Andrew Stewart [2008-01-15 18:32]:

I believe one can add methods to a class by including a module
but not override existing methods.

well, you *can* override them explicitly:

  module Bar
    def self.included(base)
      methods_to_override = %w[answer]
                          # or even <tt>instance_methods(false)</tt>

      methods_to_override.each { |method|
        base.send(:define_method, method, instance_method(method))
      }
    end
  end

if that's what you want... :wink:

cheers
jens

···

--
Jens Wille, Dipl.-Bibl. (FH)
prometheus - Das verteilte digitale Bildarchiv für Forschung & Lehre
Kunsthistorisches Institut der Universität zu Köln
Albertus-Magnus-Platz, D-50923 Köln
Tel.: +49 (0)221 470-6668, E-Mail: jens.wille@uni-koeln.de
http://www.prometheus-bildarchiv.de/

i personally avoid aliases like that - they stack when you double require or double include a module and throw into a loop. this kind of thing can be done safely and generically using a variable for the previous method that's protected from the gc and a lookup in the new method:

cfp:~ > cat a.rb
class A
   def foo
     p "A.foo"
   end
end
class B
end

module M
   NoGC =

   def self.included other
     other.module_eval do
       if((foo = instance_method 'foo' rescue false))
         NoGC.push foo
         supra = "ObjectSpace._id2ref(#{ foo.object_id }).bind(self).call(*a, &b)"
       end
       eval <<-code
         def foo *a, &b
           #{ supra }
           p "M.foo"
         end
       code
     end
   end
end

A.send :include, M
B.send :include, M

A.new.foo
B.new.foo

cfp:~ > ruby a.rb
"A.foo"
"M.foo"

this allows you to both override and super up, in any combination, with a method injected late into a class hierarchy

kind regards

a @ http://codeforpeople.com/

···

On Jan 15, 2008, at 10:32 AM, Andrew Stewart wrote:

Hi Everyone,

I believe one can add methods to a class by including a module but not override existing methods. Indeed Dr Nic said as much here:

http://ruby.tie-rack.org/6/safely-overriding-method_missing-in-a-class-that-already-has-it/#comment-7

--
it is not enough to be compassionate. you must act.
h.h. the 14th dalai lama

Aha, of course. Thank you for the clear explanation.

I really should have worked that one out myself!

With regards,
Andy Stewart

···

On 15 Jan 2008, at 17:40, Robert Klemme wrote:

Because of the position in the inheritance hierarchy:

irb(main):001:0> module Bar;end
=> nil
irb(main):002:0> class Foo
irb(main):003:1> include Bar
irb(main):004:1> end
=> Foo
irb(main):005:0> Foo.ancestors
=> [Foo, Bar, Object, Kernel]

Methods defined in Foo are always found before their counterparts in included modules. Consequently you can override super class methods with a module.

-------

Actually whenever these issues come up I wonder why we still define
methods in classes?
Either, using pure Ruby implementening all functionality im Modules
(with the dangerous pitfall of double inclusion, or just using Traits
Composition would just end all of that kind of complexity) But even I
do not use my Traits package, old habits are difficult to lose
indeed....
Cheers
Robert

···

On Jan 15, 2008 8:33 PM, ara.t.howard <ara.t.howard@gmail.com> wrote:

this allows you to both override and super up, in any combination,
with a method injected late into a class hierarchy

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

There's always a way! Thanks Jens, that's neat.

Regards,
Andy Stewart

···

On 15 Jan 2008, at 18:15, Jens Wille wrote:

well, you *can* override them explicitly:

  module Bar
    def self.included(base)
      methods_to_override = %w[answer]
                          # or even <tt>instance_methods(false)</tt>

      methods_to_override.each { |method|
        base.send(:define_method, method, instance_method(method))
      }
    end
  end

if that's what you want... :wink:

-------

i personally avoid aliases like that - they stack when you double require or double include a module and throw into a loop. this kind of thing can be done safely and generically using a variable for the previous method that's protected from the gc and a lookup in the new method:

I see. That sounds much more sensible.

cfp:~ > cat a.rb
class A
  def foo
    p "A.foo"
  end
end
class B
end

module M
  NoGC =

  def self.included other
    other.module_eval do
      if((foo = instance_method 'foo' rescue false))
        NoGC.push foo
        supra = "ObjectSpace._id2ref(#{ foo.object_id }).bind(self).call(*a, &b)"
      end
      eval <<-code
        def foo *a, &b
          #{ supra }
          p "M.foo"
        end
      code
    end
  end
end

A.send :include, M
B.send :include, M

A.new.foo
B.new.foo

cfp:~ > ruby a.rb
"A.foo"
"M.foo"

this allows you to both override and super up, in any combination, with a method injected late into a class hierarchy

Wonderful!

I should confess that I haven't entirely convinced myself that I understand your construction of supra. Given that you have the unbound method in the foo variable, is the reason why you can't bind foo directly, perhaps like this:

     supra = "#{foo}.bind(self).call(*a, &b)"

...because there's no way to write the string so it eval's the way we want it to?

Thank you for the enlightenment :slight_smile:

Regards,
Andy Stewart

···

On 15 Jan 2008, at 19:33, ara.t.howard wrote:

-------

Are you a talented Ruby on Rails or mod_perl Developer looking for an
exciting opportunity? My client runs a leading enthusiasts
community/e-commerce site and they need your expertise to create new
features and functions related to social networking. This is a great
opportunity to work with a fun group and contribute to exciting
technology that's used by many!

Qualifications:

* Thorough understanding of object-oriented methodology
* Thorough understanding of MVC architectures
* Experience with coding database-backed web applications
* Expert knowledge in either mod_perl or Ruby on Rails
* Intermediate knowledge of a mod_perl templating language
* Intermediate CSS and Javascript skills
* Willingness to work in an Agile development environment
* Ability to clearly and concisely communicate technical ideas

If you are interested or know someone that is interested please have
them email a resume as a Word attachment to betsyb@parkerservices.com or
sbaker@parkerservices.com

Thanks!
Scot Baker
Technical Recruiting Manager
parker technical
605 Fifth Avenue South -Suite 850- Seattle, WA 98104
sbaker@parkerservices.com | p: 206-652-1587 | f: 206-223-8227 |
c:206-915-9020
http://www.linkedin.com/in/scotbaker

Because of the position in the inheritance hierarchy:

irb(main):001:0> module Bar;end
=> nil
irb(main):002:0> class Foo
irb(main):003:1> include Bar
irb(main):004:1> end
=> Foo
irb(main):005:0> Foo.ancestors
=> [Foo, Bar, Object, Kernel]

Methods defined in Foo are always found before their counterparts in included modules. Consequently you can override super class methods with a module.

Aha, of course. Thank you for the clear explanation.

You're welcome!

I really should have worked that one out myself!

Ah, no worries. Once in a while this just happens to all of us.

Btw, you got a nice website there (with a typo on the vortex page *g*).

Kind regards

  robert

···

On 15.01.2008 19:10, Andrew Stewart wrote:

On 15 Jan 2008, at 17:40, Robert Klemme wrote:

Where is this at? This is one of the most vague job listings I've ever seen.

I'm assuming Seattle?

--Jeremy

···

On Jan 15, 2008 1:29 PM, Scot H. Baker <sbaker@parkerservices.com> wrote:

Are you a talented Ruby on Rails or mod_perl Developer looking for an
exciting opportunity? My client runs a leading enthusiasts
community/e-commerce site and they need your expertise to create new
features and functions related to social networking. This is a great
opportunity to work with a fun group and contribute to exciting
technology that's used by many!

Qualifications:

* Thorough understanding of object-oriented methodology
* Thorough understanding of MVC architectures
* Experience with coding database-backed web applications
* Expert knowledge in either mod_perl or Ruby on Rails
* Intermediate knowledge of a mod_perl templating language
* Intermediate CSS and Javascript skills
* Willingness to work in an Agile development environment
* Ability to clearly and concisely communicate technical ideas

If you are interested or know someone that is interested please have
them email a resume as a Word attachment to betsyb@parkerservices.com or
sbaker@parkerservices.com

Thanks!
Scot Baker
Technical Recruiting Manager
parker technical
605 Fifth Avenue South -Suite 850- Seattle, WA 98104
sbaker@parkerservices.com | p: 206-652-1587 | f: 206-223-8227 |
c:206-915-9020
Scot Baker - Baker Technical Talent | LinkedIn

--
http://www.jeremymcanally.com/

My books:
Ruby in Practice

My free Ruby e-book

My blogs:

http://www.rubyinpractice.com/

Thanks! You are kind to say so.

I can't find that typo though...are you pulling my leg? :slight_smile:

With regards,
Andy Stewart

···

On 15 Jan 2008, at 18:39, Robert Klemme wrote:

Btw, you got a nice website there (with a typo on the vortex page *g*).

-------

As long as it's close to a Soup Kitchen they have the free lunch thing
covered.

···

On Jan 15, 2008 12:19 PM, Jeremy McAnally <jeremymcanally@gmail.com> wrote:

Where is this at? This is one of the most vague job listings I've ever
seen.

I'm assuming Seattle?

--Jeremy

On Jan 15, 2008 1:29 PM, Scot H. Baker <sbaker@parkerservices.com> wrote:
>
> Are you a talented Ruby on Rails or mod_perl Developer looking for an
> exciting opportunity? My client runs a leading enthusiasts
> community/e-commerce site and they need your expertise to create new
> features and functions related to social networking. This is a great
> opportunity to work with a fun group and contribute to exciting
> technology that's used by many!
>
> Qualifications:
>
> * Thorough understanding of object-oriented methodology
> * Thorough understanding of MVC architectures
> * Experience with coding database-backed web applications
> * Expert knowledge in either mod_perl or Ruby on Rails
> * Intermediate knowledge of a mod_perl templating language
> * Intermediate CSS and Javascript skills
> * Willingness to work in an Agile development environment
> * Ability to clearly and concisely communicate technical ideas
>
> If you are interested or know someone that is interested please have
> them email a resume as a Word attachment to betsyb@parkerservices.com or
> sbaker@parkerservices.com
>
> Thanks!
> Scot Baker
> Technical Recruiting Manager
> parker technical
> 605 Fifth Avenue South -Suite 850- Seattle, WA 98104
> sbaker@parkerservices.com | p: 206-652-1587 | f: 206-223-8227 |
> c:206-915-9020
> Scot Baker - Baker Technical Talent | LinkedIn
>
>
>
>

--
http://www.jeremymcanally.com/

My books:
Ruby in Practice
Ruby in Practice

My free Ruby e-book
http://www.humblelittlerubybook.com/

My blogs:
http://www.mrneighborly.com/
http://www.rubyinpractice.com/

--
"Hey brother Christian with your high and mighty errand, Your actions speak
so loud, I can't hear a word you're saying."

-Greg Graffin (Bad Religion)

I think he was joking since Americans typically use "specialize" and
"center" instead :slight_smile:

Todd

···

On Jan 16, 2008 10:06 AM, Andrew Stewart <boss@airbladesoftware.com> wrote:

On 15 Jan 2008, at 18:39, Robert Klemme wrote:
> Btw, you got a nice website there (with a typo on the vortex page
> *g*).

Thanks! You are kind to say so.

I can't find that typo though...are you pulling my leg? :slight_smile:

Btw, you got a nice website there (with a typo on the vortex page
*g*).

Thanks! You are kind to say so.

You're welcome! I really like the clean design. You know, I am more the "Braun" type than the "Hundertwasser" type. Also, I noticed you use Mongrel for hosting. :slight_smile:

I can't find that typo though...are you pulling my leg? :slight_smile:

I think he was joking since Americans typically use "specialize" and
"center" instead :slight_smile:

Nope. First, I am not American* and second, these are not the words I had in mind. The "offending" word is somewhere between "organised" and "David Allen's". To give an additional hint, it's spelled correct *and* wrong in the *same* paragraph. :slight_smile:

Cheers

  robert

* Although I have to say that most English I am exposed to is probably American English. :slight_smile:

···

On 16.01.2008 19:19, Todd Benson wrote:

On Jan 16, 2008 10:06 AM, Andrew Stewart <boss@airbladesoftware.com> wrote:

On 15 Jan 2008, at 18:39, Robert Klemme wrote:

Got it. Easy to miss. Also, I assumed you were talking about the home page.

cheers,
Todd

···

On Jan 16, 2008 1:39 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

Nope. First, I am not American* and second, these are not the words I
had in mind.

Got it. Quelle gaffe!

I like to take pride in shunning automatic spell-checking...so I shouldn't be surprised when a fall follows :slight_smile:

Kind regards,
Andy Stewart

···

On 16 Jan 2008, at 19:39, Robert Klemme wrote:

The "offending" word is somewhere between "organised" and "David Allen's". To give an additional hint, it's spelled correct *and* wrong in the *same* paragraph. :slight_smile:

-------