From: Robert Dober Date: 2007-05-06T20:14:17+09:00 Subject: Re: how to define a method template On 5/6/07, 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 < 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 > => # > irb(main):011:0> f.apple > NoMethodError: undefined method `apple' for # > 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