I’m not sure one way is technically better than the other, so if anyone
has any input, I’d be glad to hear it.
class Job
def initialize(file = nil)
raise “need file or block” if fil.nil? || !block_given?
@action = block_given? ? lambda { yield } : eval(“lambda {
#{IO.read(file)} }”)
end
def do
@action.call
end
end
or
class Job
def initialize(file = nil)
raise “need file or block” if fil.nil? || !block_given?
action = block_given? ? lambda { yield } : eval(“lambda {
#{IO.read(file)} }”)
self.class.send(:define_method, :task, action)
self.class.send(:private, :task)
end
def do
task
end
end
please forgive the typos in the original, i should learn not to type the
code directly into the form.
corrected:
class JobA
def initialize(file = nil)
raise “need file or block” if file.nil? && !block_given?
@action = block_given? ? lambda { yield } : eval(“lambda {
#{IO.read(file)} }”)
end
def do
@action.call
end
end
class JobB
def initialize(file = nil)
raise “need file or block” if file.nil? && !block_given?
action = block_given? ? lambda { yield } : eval(“lambda {
#{IO.read(file)} }”)
self.class.send(:define_method, :task, action)
self.class.send(:private, :task)
end
def do
task
end
end
This can be done in almost endless different ways of course. Here are
two other options:
class Job
def initialize(file=nil, &block)
raise "need file or block" unless file or block
@file = file
@block = block
end
def do
if @file
File.read @file
else
@block.call
end
end
end
class Job
def initialize(file=nil, &block)
raise "need file or block" unless file or block
@task = block || lambda { File.read file }
end
def do
@task.call
end
end
The second one is a slightly cleaned up version of your first
proposal.
Regards,
Thomas.
On 2/14/08, Chris H. [email protected] wrote:
@action.call
end
end
I may be missing something important about what you are trying to
accomplish, but
what about simply
class Job
def initialize(file = nil, &block)
raise “need file or block” if file.nil? && !block_given?
@action = block || proc { eval IO.read(file)}
end
def do
@action.call
end
end
(I sure hope you trust the contents of ‘file’)
-Adam
Adam S. wrote:
On 2/14/08, Chris H. [email protected] wrote:
@action.call
end
end
I may be missing something important about what you are trying to
accomplish, but
what about simply
class Job
def initialize(file = nil, &block)
raise “need file or block” if file.nil? && !block_given?
@action = block || proc { eval IO.read(file)}
end
def do
@action.call
end
end
(I sure hope you trust the contents of ‘file’)
-Adam
The main reason the code is the way it is, is because I don’t want to
used named blocks, see:
The only really difference between the 2 is that in once instance I am
capturing the block in @action and in the other I am creating a method
from the block. I didn’t know if one way was more efficient than the
other.
And yes, I will be trusting the code in file. 
I’m not necessarily looking for the simplest solution, I’m looking for
the best solution. Both of the examples I posted have the same results,
it’s just how they are implemented. I didn’t know there was some behind
the scenes mo-jo going on that makes one a better choice than the other.
irb(main):034:0> JobB.instance_method(:do)
=> #<UnboundMethod: JobB#do>
This should be :task of course. Sorry.
ThoML wrote:
Okay, I missed the deeper meaning of eval in your example.
eval("lambda {#{IO.read(file)} }")
Maybe:
@task = if file
ruby = file.read file
lambda { eval ruby }
else
block
end
I’m not necessarily looking for the simplest solution, I’m looking for
the best solution. Both of the examples I posted have the same results,
it’s just how they are implemented.
The second one creates the method in the class though which most
likely
isn’t what you want.
irb(main):032:0> j = JobB.new('test.rb')
=> #<JobB:0x7fec2adc>
irb(main):034:0> JobB.instance_method(:do)
=> #<UnboundMethod: JobB#do>
If you want to minimize the context, create a new method that gets
nothing but the file name as argument and returns the block for the
file. I think that’s what’s meant in the blog post.
so what would be the difference between:
x = eval “lambda { #{IO.read(file)}” }"
x.call
y = lambda { eval IO.read(file) }
y.call
I’m guessing that in the first eval gets called only the one time where
in the second, eval gets called with every y.call. (this is why i did
it the way i did, if i am incorrect, then please let me know)
Okay, I missed the deeper meaning of eval in your example.
eval("lambda {#{IO.read(file)} }")
Maybe:
@task = if file
ruby = file.read file
lambda { eval ruby }
else
block
end
I’m not necessarily looking for the simplest solution, I’m looking for
the best solution. Both of the examples I posted have the same results,
it’s just how they are implemented.
The second one creates the method in the class though which most
likely
isn’t what you want.
irb(main):032:0> j = JobB.new('test.rb')
=> #<JobB:0x7fec2adc>
irb(main):034:0> JobB.instance_method(:do)
=> #<UnboundMethod: JobB#do>
If you want to minimize the context, create a new method that gets
nothing but the file name as argument and returns the block for the
file. I think that’s what’s meant in the blog post.