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
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 A. wrote:
... 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...
Think you may have misread my code. Have a look at Line 2 of
edit_action_for
define_method(:edit) do
Edward
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!