0

I have a class Foo:

class Foo

    def a
        "something" if true
    end

end

I want an add_statement method to add new statements to the method, keeping the old implementation. Is it possible?

I want to do something like this:

foo = Foo.new
foo.extend_method(:a, &block)

so now the source of my a method should be something like this:

    def a
        "something" if true
        &block
    end

where &block is the code I passed as argument in extend_method.

5
  • define_method(:add_statement, instance_method(:a)) Commented Oct 5, 2015 at 17:22
  • 1
    It seems that you want to create a new method that contains the statements in a plus additional statements. Is that what you mean? Please edit and add an example. ("dynamically" in the title is misspelled.) Commented Oct 5, 2015 at 17:36
  • I edited it, check it out Commented Oct 5, 2015 at 17:57
  • I don't think that is a good idea. It is a potentially uncontrollable code at runtime. Maybe you should think another way. What do you want to do exactly? Commented Oct 5, 2015 at 18:07
  • Too many times we get asked about an "XY problem", where the question is about Y which is the implementation of a solution, when it should be X, which is the problem and how it could be solved. This question has the smell of a "Y". Please explain what you want to do. Also, don't add "EDIT" or "UPDATE", instead simply incorporate the information where it belongs in the question as if you'd included it in the first place. Commented Oct 5, 2015 at 20:03

2 Answers 2

1

You want to use alias_method_chain, or Module#prepend.

There are many tutorials / documentation about them on the net, for example "AVOIDING ALIAS_METHOD_CHAIN IN RUBY" or "Module.prepend: a super story".

For your specific example (when you want to extend the function outside of the class), you have to use alias_method_chain, added in a new module, and included in your original class using Foo.send.

You can find more details and examples in "When to use alias_method_chain".

Sign up to request clarification or add additional context in comments.

1 Comment

Module#prepend is a good solution I've used for similar situations where I needed to change behavior of require and require_relative. Also, instead of "this or this", provide usable anchor text that allows people to quickly and easily see where the link will take them without having to actually click it to see.
0

Here is an aspect oriented example:

require 'aspector'

class Foo
  def a
    puts "in Foo.a"
  end
end

aspect = Aspector do
  before :a do
    puts 'this should print first'
  end

  after :a do |result_of_a|
    puts 'this should print last'
  end
end

puts "\n\nplain instance"
foo = Foo.new
foo.a

puts "\n\napply to an instance"
aspect.apply(foo)
foo.a

puts "\n\napply to all instances of Foo"
aspect.apply(Foo)
Foo.new.a

You will need to 'gem install aspector'.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.