Is there a possibility to include methods of a class?

Hi all,
first of all: this list and you rock! I know that there is no multiple
inheritance, but you can use the concept of mixin.
However, I want to inherit my class another and “mixin” methods from
another class.
To be more precise,
I have a class that inherits another one (that comes from a library and
I do not want to change) and I want the methods of ActiveRecord::Base in
my class. Is there a way to do that (without copying and paste the whole
ActiveRecord::Base class and changing it to a module)?

Thanks in advance!

Bernd pisze:

Thanks in advance!

Yes, You can use evil ruby http://rubyforge.org/projects/evil
like this:
class Bar
include Array.as_module
end

b = Bar.new
b.push(1,2,3)
p b # => [1,2,3]

but this is bad resolve of your problem.

Mariusz Pietrzyk wrote:

Bernd pisze:

Thanks in advance!

Yes, You can use evil ruby http://rubyforge.org/projects/evil
like this:
class Bar
include Array.as_module
end

b = Bar.new
b.push(1,2,3)
p b # => [1,2,3]

but this is bad resolve of your problem.

I just thought, if there is a possibility to do dynamic inheritance like

def some_method
Some_class < ActiveRecord::Base
end

On Fri, May 11, 2007 at 10:29:01PM +0900, Bernd wrote:

Hi all,
first of all: this list and you rock! I know that there is no multiple
inheritance, but you can use the concept of mixin.
However, I want to inherit my class another and “mixin” methods from
another class.
To be more precise,
I have a class that inherits another one (that comes from a library and
I do not want to change) and I want the methods of ActiveRecord::Base in
my class. Is there a way to do that (without copying and paste the whole
ActiveRecord::Base class and changing it to a module)?

I would use delegation for one class or the other.

That is: define your class as

class Foo < ActiveRecord::Base

def initialize
@other = Library::Bar.new
end
end

Or vice versa, whichever makes more sense. And if you can’t choose, then
delegate to both.

class FooDB < ActiveRecord::Base
… more stuff
end

class Foo
def initialize(id)
@db = FooDB.find(id)
@lib = Library::Bar.new
end
end

Then the interface that Foo exposes to the world can pass some calls to
@db,
some to @lib, or (the best news) can combine behaviours from both in
whichever way it likes.

Brian C. wrote:

On Fri, May 11, 2007 at 10:29:01PM +0900, Bernd wrote:

Hi all,
first of all: this list and you rock! I know that there is no multiple
inheritance, but you can use the concept of mixin.
However, I want to inherit my class another and “mixin” methods from
another class.
To be more precise,
I have a class that inherits another one (that comes from a library and
I do not want to change) and I want the methods of ActiveRecord::Base in
my class. Is there a way to do that (without copying and paste the whole
ActiveRecord::Base class and changing it to a module)?

I would use delegation for one class or the other.

That is: define your class as

class Foo < ActiveRecord::Base

def initialize
@other = Library::Bar.new
end
end

Or vice versa, whichever makes more sense. And if you can’t choose, then
delegate to both.

class FooDB < ActiveRecord::Base
… more stuff
end

class Foo
def initialize(id)
@db = FooDB.find(id)
@lib = Library::Bar.new
end
end

Then the interface that Foo exposes to the world can pass some calls to
@db,
some to @lib, or (the best news) can combine behaviours from both in
whichever way it likes.

This is the workaround I just had so far, and now I want to get rid of
it.

I have two classes:
class Myclass < ActiveRecord::Base
def self.find(number)
Anotherclass.find(number)
end

class Anotherclass < SAP4Rails::Base
def self.find(number)
do something
end

But this solution to me seems to be so un-ruby!

As SAP4Rails::Base does not have an explicit superclass, I wondered, if
there is some way to inject it dynamically a super class, because I need
some other methods from ActiveRecord in another application
I know that I could just alter the SAP4Rails class, but I want it in the
way, that you just need ActiveRecord, SAP4RAils and my piece of code.

Mariusz Pietrzyk wrote:

Bernd pisze:

Thanks in advance!

Yes, You can use evil ruby http://rubyforge.org/projects/evil
like this:
class Bar
include Array.as_module
end

b = Bar.new
b.push(1,2,3)
p b # => [1,2,3]

but this is bad resolve of your problem.

I think that would be the ruby way, following the principle of least
surprise. Unfortunately, neither Array nor ActiveRecord::Base do have an
“as_module” method :frowning:

On Sat, May 12, 2007 at 12:30:00AM +0900, Bernd B. wrote:

def self.find(number)
do something
end

But this solution to me seems to be so un-ruby!

You seem to be doing something very strange in the above code. You are
replacing one of ActiveRecord::Base’s most fundamental operations - load
from database by ID - with something which does something completely
different.

Are you also going to overwrite the save and update methods? In which
case,
what functionality from ActiveRecord::Base do you actually want to keep?

I am guessing that SAP4Rails is some sort of remote-procedure call
wrapper.
That is, an instance of SAP4Rails::Base represents an object on some
remote
SAP server. If that’s true, I don’t see how it makes sense to try to mix
that with another object which represents a row in a local SQL database.

If Myclass represents something which may exist in the local database
and/or
in the remote SAP system, then I’d very much go for delegation.

class MyDb < ActiveRecord::Base; end
class MySap < SAP4Rails::Base; end

class Myclass
def self.find(number)
@rec = MyDb.find(number)
@sap = MySap.find(number)
end
end

Then you are making it explicit that you are talking about two different
things, and you can implement useful operations (such as copy data from
one
to the other)

Regards,

Brian.

On Sat, May 12, 2007 at 01:19:26AM +0900, Brian C. wrote:

class Anotherclass < SAP4Rails::Base

Then you are making it explicit that you are talking about two different
things, and you can implement useful operations (such as copy data from one
to the other)

P.S. Something which may be relevant as an example is ActiveResource.

This is a REST XML client library, which presents an API very similar to
ActiveRecord: e.g.

class Foo < ActiveResource::Base
self.site = “http://localhost:3000
end

foo = Foo.find(2) # performs GET /foo/2.xml
foos = Foo.find(:all) # performs GET /foo.xml

But this doesn’t re-use any of ActiveRecord. Whilst the interface is
similar in some ways, the underlying operations are very different.

ActiveRecord is very much a wrapper around a SQL database. Almost all
the
operations you can perform ultimately get translated into calls on the
database connection for SELECT, UPDATE etc.

The other useful bits of ActiveRecord, like validations, are already
mixins
in their own right. That is, they come pre-mixed into
ActiveRecord::Base,
but you could mix them into your own class independently.

Regards,

Brian.

On 11 May 2007, at 17:14, Brian C. wrote:

I do not want to change) and I want the methods of

… more stuff
calls to @db,
some to @lib, or (the best news) can combine behaviours from both in
whichever way it likes.

That would actually be a so called Bridge Design Pattern… I like it
I think I will use it for Ruby Patterns :wink:

Thanks Brian!