[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Is there a possibility to include methods of a class?

Bernd

5/11/2007 1:29:00 PM

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!

--
Posted via http://www.ruby-....

8 Answers

Mariusz Pietrzyk

5/11/2007 1:58:00 PM

0

Bernd pisze:
> 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!
>
Yes, You can use evil ruby http://rubyforge.org/pro...
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.

Bernd Burnt

5/11/2007 2:28:00 PM

0

Mariusz Pietrzyk wrote:
> Bernd pisze:
>>
>> Thanks in advance!
>>
> Yes, You can use evil ruby http://rubyforge.org/pro...
> 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

--
Posted via http://www.ruby-....

Brian Candler

5/11/2007 3:14:00 PM

0

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.

Enrique Comba Riepenhausen

5/11/2007 3:18:00 PM

0


On 11 May 2007, at 17:14, Brian Candler 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.
>
That would actually be a so called Bridge Design Pattern... I like it
I think I will use it for Ruby Patterns ;)

Thanks Brian!


Bernd Burnt

5/11/2007 3:30:00 PM

0

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

--
Posted via http://www.ruby-....

Bernd Burnt

5/11/2007 4:02:00 PM

0

Mariusz Pietrzyk wrote:
> Bernd pisze:
>>
>> Thanks in advance!
>>
> Yes, You can use evil ruby http://rubyforge.org/pro...
> 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 :-(

--
Posted via http://www.ruby-....

Brian Candler

5/11/2007 4:19:00 PM

0

On Sat, May 12, 2007 at 12:30:00AM +0900, Bernd Burnt wrote:
> 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!

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.

Brian Candler

5/11/2007 4:42:00 PM

0

On Sat, May 12, 2007 at 01:19:26AM +0900, Brian Candler wrote:
> On Sat, May 12, 2007 at 12:30:00AM +0900, Bernd Burnt wrote:
> > 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!
>
> 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)

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.