I was looking at my controller code and the edit/create/update/new for each are practically identical. So first I DRY''d the four methods in each controller to just one and then I decided to write a single macro for all my controllers. This is the macro: def self.edit_action_for(model, options = {}) model_class = Object.const_get(model) define_method(:edit) do edit_code = lambda do @thing = model_class.find_by_id(params[:id]) || model_class.new if request.post? @thing.attributes = params[:impactable_area] if @thing.save flash[:notice] = "#{model.humanize} successfully saved." redirect_to :action => ''list'' end end end end end Then I expected this edit_action_for :ImpactableArea to create my "edit" method. Problem is that it doesn''t :-( So then I looked to see how I could do a macro expansion (as you can in Lisp) to see what''s being produced and I couldn''t find anything... HELP! Edward -- Posted via http://www.ruby-forum.com/.
The problem is that you''re not actually adding a new method definition to the class when you call "edit_action_for" - you''re just calling a class method. Basically you''re doing this: class Blah def self.test # do something # return something maybe? return ''hello!'' # in this case end # now call this test end ==> ''hello!'' ... not what you want. In your abstracted-out class method, you actually want to be creating a new method to be added to the class definition in which your macro is being called. You probably want to investigate the delightful intricacies of define_method and eval/class_eval - welcome to metaprogamming... - james On 6/8/06, Edward Kenworthy <edward@kenworthy.info> wrote:> I was looking at my controller code and the edit/create/update/new for > each are practically identical. So first I DRY''d the four methods in > each controller to just one and then I decided to write a single macro > for all my controllers. > > This is the macro: > > def self.edit_action_for(model, options = {}) > model_class = Object.const_get(model) > define_method(:edit) do > edit_code = lambda do > @thing = model_class.find_by_id(params[:id]) || model_class.new > if request.post? > @thing.attributes = params[:impactable_area] > if @thing.save > flash[:notice] = "#{model.humanize} successfully saved." > redirect_to :action => ''list'' > end > end > end > end > end > > Then I expected this > > edit_action_for :ImpactableArea > > to create my "edit" method. > > Problem is that it doesn''t :-( > > So then I looked to see how I could do a macro expansion (as you can in > Lisp) to see what''s being produced and I couldn''t find anything... > > HELP! > > Edward > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- * J * ~
James Adam wrote:> <snip> > ... not what you want. In your abstracted-out class method, you > actually want to be creating a new method to be added to the class > definition in which your macro is being called. You probably want to > investigate the delightful intricacies of define_method and > eval/class_eval - welcome to metaprogamming... > > - jamesThink you may have misread my code. Have a look at Line 2 of edit_action_for define_method(:edit) do Edward -- Posted via http://www.ruby-forum.com/.
You''re absolutely right. Hopefully this will help me pay penance for my illiteracy: class Blah def self.new_thing(arg) define_method(:do_it!) do puts "ok: #{arg}" end end new_thing "monkey" end b = Blah.new b.do_it! # ==> ok: monkey module Mung def self.new_thing(arg) define_method(:do_it!) do puts "ok: #{arg}" end end end class Jazz include Mung new_thing "baboon" end j = Jazz.new j.do_it! # ==> undefined method `new_thing'' for Jazz:Class (NoMethodError) module Soul def self.included(base) base.extend(ClassMethods) end module ClassMethods def new_thing(arg) define_method(:do_it!) do puts "Hit it; #{arg}" end end end end class Funk include Soul new_thing "Watch me now!" end f = Funk.new f.do_it! # ==> Hit it; Watch me now! - james On 6/8/06, Edward Kenworthy <edward@kenworthy.info> wrote:> James Adam wrote: > > <snip> > > ... not what you want. In your abstracted-out class method, you > > actually want to be creating a new method to be added to the class > > definition in which your macro is being called. You probably want to > > investigate the delightful intricacies of define_method and > > eval/class_eval - welcome to metaprogamming... > > > > - james > > Think you may have misread my code. Have a look at Line 2 of > edit_action_for > > define_method(:edit) do > > Edward > > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- * J * ~