Macros and stuff


#1

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 :frowning:

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


#2

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

#3

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...
  • james

Think you may have misread my code. Have a look at Line 2 of
edit_action_for

define_method(:edit) do

Edward


#4

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