Forum: Ruby on Rails Macros and stuff

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Edward K. (Guest)
on 2006-06-08 18:44
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
James A. (Guest)
on 2006-06-08 20:48
(Received via mailing list)
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
Edward K. (Guest)
on 2006-06-08 21:34
James A. 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
James A. (Guest)
on 2006-06-09 03:04
(Received via mailing list)
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
This topic is locked and can not be replied to.