[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Conditionally Including Methods From A Module?

Kenny

10/25/2008 9:02:00 AM

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
4 Answers

Mike Gold

10/25/2008 11:01:00 AM

0

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-....

Kenny

10/25/2008 11:16:00 PM

0

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

Daniel Berger

10/26/2008 12:51:00 AM

0

On Oct 25, 3:04=A0am, Kenny <kennycarruth...@gmail.com> 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

1/8/2009 6:30:00 AM

0

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/exa... for more
examples.

Regards,

Dan