[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

how to define a method template

Nanyang Zhan

5/6/2007 8:36:00 AM

Forgive me for the nonstandard words. I will describe my problem in
details:
I am doing a rails app, and met a ruby problem.
Inside a model class, I will need to write these codes for "apple"
def apple_attr
apples.collect {|o| o.name}.join(" ")
end

def apple_attr=(str)
@apple = str
end

def save_apple
#lots of codes
end

then banana, cat, dog.. each will have a copy of above codes. They are
the same, except replacing the word "apple" with "banana", "cat",
"dog"....

I know there is a way to put these code in to a module, then mixin the
module with current class, after that, you just need to call a method
(like setup_methods(:apple); setup_methods(:dog)...), instead of typing
the repeated code.

Would any one tell me how to do it?

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

9 Answers

Robert Klemme

5/6/2007 10:50:00 AM

0

On 06.05.2007 10:36, Nanyang Zhan wrote:
> Forgive me for the nonstandard words. I will describe my problem in
> details:
> I am doing a rails app, and met a ruby problem.
> Inside a model class, I will need to write these codes for "apple"
> def apple_attr
> apples.collect {|o| o.name}.join(" ")
> end
>
> def apple_attr=(str)
> @apple = str
> end
>
> def save_apple
> #lots of codes
> end
>
> then banana, cat, dog.. each will have a copy of above codes. They are
> the same, except replacing the word "apple" with "banana", "cat",
> "dog"....
>
> I know there is a way to put these code in to a module, then mixin the
> module with current class, after that, you just need to call a method
> (like setup_methods(:apple); setup_methods(:dog)...), instead of typing
> the repeated code.
>
> Would any one tell me how to do it?

Why not create all the methods on the fly? Like

class Foo
def setup_methods(sym)
cl = class <<self;self;end
cl.class_eval do
attr_accessor sym
end
cl.class_eval "def #{sym}_save() puts 'saving #{sym}' end"
end
end

Now you can do

irb(main):010:0> f=Foo.new
=> #<Foo:0x7ff74f48>
irb(main):011:0> f.apple
NoMethodError: undefined method `apple' for #<Foo:0x7ff74f48>
from (irb):11
from :0
irb(main):012:0> f.setup_methods :apple
=> nil
irb(main):013:0> f.apple
=> nil
irb(main):014:0> f.apple="foo bar"
=> "foo bar"
irb(main):015:0> f.apple
=> "foo bar"
irb(main):016:0> f.apple_save
saving apple
=> nil
irb(main):017:0>

Kind regards

robert

Robert Klemme

5/6/2007 10:51:00 AM

0

On 06.05.2007 12:49, Robert Klemme wrote:
> On 06.05.2007 10:36, Nanyang Zhan wrote:
>> Forgive me for the nonstandard words. I will describe my problem in
>> details:
>> I am doing a rails app, and met a ruby problem.
>> Inside a model class, I will need to write these codes for "apple"
>> def apple_attr
>> apples.collect {|o| o.name}.join(" ")
>> end
>>
>> def apple_attr=(str)
>> @apple = str
>> end
>>
>> def save_apple
>> #lots of codes
>> end
>>
>> then banana, cat, dog.. each will have a copy of above codes. They are
>> the same, except replacing the word "apple" with "banana", "cat",
>> "dog"....
>>
>> I know there is a way to put these code in to a module, then mixin the
>> module with current class, after that, you just need to call a method
>> (like setup_methods(:apple); setup_methods(:dog)...), instead of typing
>> the repeated code.
>>
>> Would any one tell me how to do it?
>
> Why not create all the methods on the fly? Like
>
> class Foo
> def setup_methods(sym)
> cl = class <<self;self;end
> cl.class_eval do
> attr_accessor sym
> end
> cl.class_eval "def #{sym}_save() puts 'saving #{sym}' end"
> end
> end
>
> Now you can do
>
> irb(main):010:0> f=Foo.new
> => #<Foo:0x7ff74f48>
> irb(main):011:0> f.apple
> NoMethodError: undefined method `apple' for #<Foo:0x7ff74f48>
> from (irb):11
> from :0
> irb(main):012:0> f.setup_methods :apple
> => nil
> irb(main):013:0> f.apple
> => nil
> irb(main):014:0> f.apple="foo bar"
> => "foo bar"
> irb(main):015:0> f.apple
> => "foo bar"
> irb(main):016:0> f.apple_save
> saving apple
> => nil
> irb(main):017:0>
>
> Kind regards
>
> robert

PS: of course you can define setup_methods in a module and mixin that
module.

Robert Dober

5/6/2007 11:14:00 AM

0

On 5/6/07, Robert Klemme <shortcutter@googlemail.com> wrote:
> On 06.05.2007 10:36, Nanyang Zhan wrote:
> > Forgive me for the nonstandard words. I will describe my problem in
> > details:
> > I am doing a rails app, and met a ruby problem.
> > Inside a model class, I will need to write these codes for "apple"
> > def apple_attr
> > apples.collect {|o| o.name}.join(" ")
> > end
> >
> > def apple_attr=(str)
> > @apple = str
> > end
> >
> > def save_apple
> > #lots of codes
> > end
> >
> > then banana, cat, dog.. each will have a copy of above codes. They are
> > the same, except replacing the word "apple" with "banana", "cat",
> > "dog"....
> >
> > I know there is a way to put these code in to a module, then mixin the
> > module with current class, after that, you just need to call a method
> > (like setup_methods(:apple); setup_methods(:dog)...), instead of typing
> > the repeated code.
> >
> > Would any one tell me how to do it?
>
> Why not create all the methods on the fly? Like
>
> class Foo
> def setup_methods(sym)
> cl = class <<self;self;end
> cl.class_eval do
> attr_accessor sym
> end
> cl.class_eval "def #{sym}_save() puts 'saving #{sym}' end"
> end
> end
Robert I have understood the setup a little bit differently, was it
not on the class base that OP wanted his methods?

Your technique of course is correct, just that - if I were right - OP
needed this

class Foo

%w{ apple banana mango strawberry }.each do
|fruit|
define_method "#{fruit}_attr" do
send(fruit.pluralize).map{|f|f.name}.join(",")
end
define_method "#{fruit}_attr=" do
| str |
instance_variable_set("@" << fruit, str)
end
define_method "save_" << fruit do
# lots of code adapted to metaprogramming, which might be possible :)
# or not :(
end
end
end
>
> Now you can do
>
> irb(main):010:0> f=Foo.new
> => #<Foo:0x7ff74f48>
> irb(main):011:0> f.apple
> NoMethodError: undefined method `apple' for #<Foo:0x7ff74f48>
> from (irb):11
> from :0
> irb(main):012:0> f.setup_methods :apple
> => nil
> irb(main):013:0> f.apple
> => nil
> irb(main):014:0> f.apple="foo bar"
> => "foo bar"
> irb(main):015:0> f.apple
> => "foo bar"
> irb(main):016:0> f.apple_save
> saving apple
> => nil
> irb(main):017:0>
>
> Kind regards
>
> robert
>
>

f = Foo.new # has methods like apples_attr, save_strawberry and
banana_attr= already, which might make sense or not

HTH
Robert
--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Robert Klemme

5/6/2007 1:24:00 PM

0

On 06.05.2007 13:14, Robert Dober wrote:
> On 5/6/07, Robert Klemme <shortcutter@googlemail.com> wrote:
>> On 06.05.2007 10:36, Nanyang Zhan wrote:
>> > Forgive me for the nonstandard words. I will describe my problem in
>> > details:
>> > I am doing a rails app, and met a ruby problem.
>> > Inside a model class, I will need to write these codes for "apple"
>> > def apple_attr
>> > apples.collect {|o| o.name}.join(" ")
>> > end
>> >
>> > def apple_attr=(str)
>> > @apple = str
>> > end
>> >
>> > def save_apple
>> > #lots of codes
>> > end
>> >
>> > then banana, cat, dog.. each will have a copy of above codes. They are
>> > the same, except replacing the word "apple" with "banana", "cat",
>> > "dog"....
>> >
>> > I know there is a way to put these code in to a module, then mixin the
>> > module with current class, after that, you just need to call a method
>> > (like setup_methods(:apple); setup_methods(:dog)...), instead of typing
>> > the repeated code.
>> >
>> > Would any one tell me how to do it?
>>
>> Why not create all the methods on the fly? Like
>>
>> class Foo
>> def setup_methods(sym)
>> cl = class <<self;self;end
>> cl.class_eval do
>> attr_accessor sym
>> end
>> cl.class_eval "def #{sym}_save() puts 'saving #{sym}' end"
>> end
>> end
> Robert I have understood the setup a little bit differently, was it
> not on the class base that OP wanted his methods?

Maybe. His statement seems to be a bit contradictory. First he talks
about all these methods being there. Then he mentions some method
setup_methods which I believe is to create those methods. But you're
right, could also be a class method (like attr_accessor). OP, what do
you want - Robert's solution or Robert's solution? :-)

Kind regards

robert

Robert Dober

5/6/2007 3:25:00 PM

0

On 5/6/07, Robert Klemme <shortcutter@googlemail.com> wrote:
> On 06.05.2007 13:14, Robert Dober wrote:
> > On 5/6/07, Robert Klemme <shortcutter@googlemail.com> wrote:
> >> On 06.05.2007 10:36, Nanyang Zhan wrote:
> >> > Forgive me for the nonstandard words. I will describe my problem in
> >> > details:
> >> > I am doing a rails app, and met a ruby problem.
> >> > Inside a model class, I will need to write these codes for "apple"
> >> > def apple_attr
> >> > apples.collect {|o| o.name}.join(" ")
> >> > end
> >> >
> >> > def apple_attr=(str)
> >> > @apple = str
> >> > end
> >> >
> >> > def save_apple
> >> > #lots of codes
> >> > end
> >> >
> >> > then banana, cat, dog.. each will have a copy of above codes. They are
> >> > the same, except replacing the word "apple" with "banana", "cat",
> >> > "dog"....
> >> >
> >> > I know there is a way to put these code in to a module, then mixin the
> >> > module with current class, after that, you just need to call a method
> >> > (like setup_methods(:apple); setup_methods(:dog)...), instead of typing
> >> > the repeated code.
> >> >
> >> > Would any one tell me how to do it?
> >>
> >> Why not create all the methods on the fly? Like
> >>
> >> class Foo
> >> def setup_methods(sym)
> >> cl = class <<self;self;end
> >> cl.class_eval do
> >> attr_accessor sym
> >> end
> >> cl.class_eval "def #{sym}_save() puts 'saving #{sym}' end"
> >> end
> >> end
> > Robert I have understood the setup a little bit differently, was it
> > not on the class base that OP wanted his methods?
>
> Maybe. His statement seems to be a bit contradictory. First he talks
> about all these methods being there. Then he mentions some method
> setup_methods which I believe is to create those methods. But you're
> right, could also be a class method (like attr_accessor). OP, what do
> you want - Robert's solution or Robert's solution? :-)
Difficult decision LOL
>
> Kind regards
>
> robert
>
>


--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Nanyang Zhan

5/6/2007 3:37:00 PM

0

> OP, what do you want - Robert's solution or Robert's solution? :-)
>
> Kind regards
>
> robert
Thanks RobertS!
Now I'm pretty sure that people tend to using the programming languages
that has the same character with their names, like Roberts will pick up
Ruby while Johns prefer Java.

Robert Dober's solution offer me details on how to write the codes about
defining those methods. It will be very useful, but still I have no idea
where to put these definitions.
Robert's solution(yes, that's Robert Klemme) needs to be adjusted to fit
my requirement correctlly. But it's very interesting. Robert, Can you
tell me how to make setup_methods :apple can be called inside a class,
like:

#magic codes put here, then
Class Fruit < ActiveRecord::Base
# create all the methods on the fly
setup_methods :apple
setup_methods :banana
....
# call methods that are created on the fly inside a class
after_save :save_apple
after_save :save_banana
end

That is, please tell me how to mixin.



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

Nanyang Zhan

5/6/2007 4:11:00 PM

0

I just managed to apply Dober's codes into my app (I just copy the code
into the class, and add some codes), It is just that simple, but works
fine! Still, I get a problem, inside
> define_method "save_" << fruit do
> #HERE
> end
this method, I need to call a local method with the same name as string
fruit contains. If it is a instance variable, I know there are
instance_variable_set("@#{fruit}", str) and
instance_variable_get("@#{fruit}") methods. But what about this local
method? How can I read/set its value?

Though the problem inside the class is almost solved, but I still want
to know the mixin solution, because with mixin solution, I can use these
code almong other classes.

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

Robert Klemme

5/6/2007 4:23:00 PM

0

On 06.05.2007 17:37, Nanyang Zhan wrote:
>> OP, what do you want - Robert's solution or Robert's solution? :-)
>>
>> Kind regards
>>
>> robert
> Thanks RobertS!
> Now I'm pretty sure that people tend to using the programming languages
> that has the same character with their names, like Roberts will pick up
> Ruby while Johns prefer Java.

Actually I do Java for a living - and I don't hate it. :-)

> Robert Dober's solution offer me details on how to write the codes about
> defining those methods. It will be very useful, but still I have no idea
> where to put these definitions.
> Robert's solution(yes, that's Robert Klemme) needs to be adjusted to fit
> my requirement correctlly. But it's very interesting. Robert, Can you
> tell me how to make setup_methods :apple can be called inside a class,
> like:
>
> #magic codes put here, then
> Class Fruit < ActiveRecord::Base
> # create all the methods on the fly
> setup_methods :apple
> setup_methods :banana
> ...
> # call methods that are created on the fly inside a class
> after_save :save_apple
> after_save :save_banana
> end
>
> That is, please tell me how to mixin.

Basically you can define a method setup_methods in class Class. Untested:

class Class
def setup_methods(sym)
class_eval do
attr_accessor sym
end
class_eval "def #{sym}_save() puts 'saving #{sym}' end"
end
end

Kind regards

robert

Nanyang Zhan

5/6/2007 5:31:00 PM

0

Robert Klemme wrote:
> Actually I do Java for a living - and I don't hate it. :-)
why hate it? while it makes you living and others happy...

> Basically you can define a method setup_methods in class Class.
Then I can call the methods it defines anywhere I like?


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