Conditionally Including Methods From A Module?

Discussion in 'Ruby' started by Kenny, Oct 25, 2008.

  1. Kenny

    Kenny Guest

    Is there a way to include only certain methods from a module instead
    of all the methods?

    Given the following:

    module ActsAsAnything
    def self.included(base)
    base.extend(ClassMethods)
    end

    module ClassMethods
    def acts_as_anything(opts = {})
    # Based on the options based in, I would like to selectively
    include certain methods from
    # the InstanceMethods module.

    # Something like:
    include ActsAsAnything::InstanceMethods.instance_method:)index)
    if opts[:include_index]
    include ActsAsAnything::InstanceMethods.instance_method:)list)
    if opts[:include_list]

    # (Note the 'if' condition above is just for example.... )
    end
    end

    module InstanceMethods
    def index
    # .....
    end

    def list
    # ....
    end
    end
    end

    However, 'include' requires a module and I can't figure out the proper
    syntax, or even if this is possible, to just include a certain method
    from it. The is for a standard acts_as_.... Rails plug-in.

    Any help or guidance is much appreciated.

    Sincerely,
    Kenny
    Kenny, Oct 25, 2008
    #1
    1. Advertising

  2. Kenny

    Mike Gold Guest

    Kenny wrote:
    > Is there a way to include only certain methods from a module instead
    > of all the methods?


    Not directly. In general, methods are part of the same module for a
    reason. A given method may call other methods in the module, and a
    method may use instance variables defined in other methods.

    What you propose could make sense in the case of a "pure utility" module
    which has no state and where there little is or no relationship between
    the methods.

    def methods_to_lambdas(mod)
    instance = Class.new { include mod }.new
    mod.instance_methods(false).inject(Hash.new) { |hash, meth|
    hash.update(
    meth.to_sym => lambda { |*args, &block|
    instance.send(meth, *args, &block)
    }
    )
    }
    end

    def pull_methods(mod, *names)
    lambdas = methods_to_lambdas(mod)
    names.each { |name|
    define_method(name, &lambdas[name])
    }
    end

    module Misc
    def func_a ; p "Misc#func_a" ; end
    def func_b ; p "Misc#func_b" ; end
    def func_c ; p "Misc#func_c" ; end
    end

    class Fred
    pull_methods(Misc, :func_a, :func_b)
    end

    Fred.new.func_a #=> Misc#func_a
    Fred.new.func_b #=> Misc#func_b
    Fred.new.func_c #=> NoMethodError

    ruby-1.8.7 or 1.9 is needed for the lambda syntax (for 1.8.6 you can
    eval a string instead).
    --
    Posted via http://www.ruby-forum.com/.
    Mike Gold, Oct 25, 2008
    #2
    1. Advertising

  3. Kenny

    Kenny Guest

    Thanks so much for the post Mike, very much appreciated and a great
    learning lesson for me in some lower level Ruby semantics.

    After my post last night, I can up with using define_method as well
    and produced something like the following:

    module ActsAsAnything
    def self.included(base)
    base.extend(ClassMethods)
    end

    module ClassMethods
    # acts_as_anything
    def acts_as_anything(opts = {})

    # index
    define_method:)index) do
    puts 'Index Method'
    end if opts.include?:)index)
    end
    end
    end

    Since I'm including a Module that I'm the author of, I figure I can
    get away with this syntax and just redefine my top level Module as
    such.

    Any thoughts on this implementation?

    Sincerely,
    Kenny
    Kenny, Oct 26, 2008
    #3
  4. On Oct 25, 3:04=A0am, Kenny <> wrote:
    > Is there a way to include only certain methods from a module instead
    > of all the methods?


    <snip>

    Yep.

    gem install use

    class Foo
    use ModuleA, :include =3D> [:method_x]
    end

    That will only include 'method_x' from ModuleA. You can also exclude
    and alias included methods on the fly.

    Regards,

    Dan
    Daniel Berger, Oct 26, 2008
    #4
  5. Kenny wrote:
    > Is there a way to include only certain methods from a module instead
    > of all the methods?
    >
    > Given the following:
    >
    > module ActsAsAnything
    > def self.included(base)
    > base.extend(ClassMethods)
    > end
    >
    > module ClassMethods
    > def acts_as_anything(opts = {})
    > # Based on the options based in, I would like to selectively
    > include certain methods from
    > # the InstanceMethods module.
    >
    > # Something like:
    > include ActsAsAnything::InstanceMethods.instance_method:)index)
    > if opts[:include_index]
    > include ActsAsAnything::InstanceMethods.instance_method:)list)
    > if opts[:include_list]
    >
    > # (Note the 'if' condition above is just for example.... )
    > end
    > end
    >
    > module InstanceMethods
    > def index
    > # .....
    > end
    >
    > def list
    > # ....
    > end
    > end
    > end
    >
    > However, 'include' requires a module and I can't figure out the proper
    > syntax, or even if this is possible, to just include a certain method
    > from it. The is for a standard acts_as_.... Rails plug-in.
    >
    > Any help or guidance is much appreciated.


    gem install use

    class Foo
    use Bar, :method_a, :method_b
    end

    See http://rubyforge.org/docman/view.php/735/2472/examples.html for more
    examples.

    Regards,

    Dan
    Daniel Berger, Jan 8, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Olav Tollefsen
    Replies:
    2
    Views:
    354
    Olav Tollefsen
    Feb 1, 2005
  2. Craig

    Conditionally including a file

    Craig, Nov 8, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    355
    Craig
    Nov 8, 2005
  3. Sten Westerback

    Including .htm files conditionally?

    Sten Westerback, Feb 3, 2004, in forum: ASP General
    Replies:
    2
    Views:
    126
    Igor Tandetnik
    Feb 3, 2004
  4. Ferenc Engard
    Replies:
    2
    Views:
    113
    Ferenc Engard
    Dec 31, 2003
  5. Nikita Petrov
    Replies:
    2
    Views:
    110
    Gary Wright
    Apr 6, 2008
Loading...

Share This Page