On Tue, Jan 25, 2011 at 4:10 AM, Tony Arcieri <tony.arcieri / medioh.com> wro=
te:
> I'm trying to write a method that builds a class and takes arguments from
> the outer scope when doing so:
>
> =A0 =A0def awesome_mcjobify(state, options =3D {}, &action)
> =A0 =A0 =A0subject_class =3D @subject_class
>
> =A0 =A0 =A0job =3D Class.new do
> =A0 =A0 =A0 =A0metaclass =3D class << self; self; end
>
> =A0 =A0 =A0 =A0metaclass.send :define_method, :perform do |id|
> =A0 =A0 =A0 =A0 =A0subject =3D subject_class.find(id)
> =A0 =A0 =A0 =A0 =A0action subject
> =A0 =A0 =A0 =A0end
>
> =A0 =A0 =A0 =A0metaclass.send :define_method, :action, &action
> =A0 =A0 =A0end
>
> =A0 =A0 =A0subject_class.const_set "#{state.to_s.camelize}Job", job
> =A0 =A0end
>
> This is trying to do a lot of things at once and feels icky. It's buildin=
g a
> class that responds to a couple of methods, encapsulates a bit of state
> (into the class itself, I guess?), then sticks that class namespaced
> underneath another given class.
>
> Refactor me? :) I know there's supposed to be define_singleton_method in
> 1.9, but using define_*method at all (not to mention send :define_method)
> seems a lot messier than it could potentially be.
>
> Any suggestions?

First thing that strikes me odd is that you define methods on the
singleton class, i.e. instance methods of the newly created class.
What do you need a class for then - especially since your new class
inherits Object (which means, it does not inherit particular instance
functionality)?  From what I see you need something that responds to
"perform" by doing two things

1. find a subject via the subject class based on the id method parameter
2. invoke the block passed with the subject found

Wouldn't this do what you need?

Proxy =3D Struct.new :subject_class, :action do
  def perform(id)
    subject =3D subject_class.find id
    action[subject]
  end
end

def awesome_mcjobify(state, options =3D {}, &action)
  Proxy[@subject_class, action]
end

It does not even need metaprogramming...

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/