On Tue, May 24, 2011 at 9:25 AM, Andreas Lundgren
<andreas.lundgren.x / gmail.com> wrote:
> My bad to use the name "param" for two different content, but any
> ways:
>
> First params typically assembles to this:
> x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s

That does not look good.  If you have to encode numbers in variable
names, you probably rather want to use an Array for that or even
generate that directly:

params = no_of_params.times.map {|i| "x#{i}"}.join(', ')

> Now I have created the code, not the string.
>
> The line
> params_2 = #{params};
> extends to:
> params_2 = x1.to_s + ', ' + x2.to_s + ', ' + x3.to_s + ', ' + x4.to_s
> and assembles my input so that
> params_2 == 'myDB, 20110101, 20110201, all'

When looking at your posting from 2:55 you don't really need "params =
..." in the generated code.

> Output from the function when STUB_CALLS=1:
> Calling shop_GetFundReq(x1, x2, x3, x4) with parameters <myDB,
> 20110101, 20110201, all>

SUB_CALLS should be a boolean and treated as such.

I can see why 7stud wrote his recommendation: the code looks overly
complicated.  Also, there are some issues, for example:

     handle.call(['MethodNameIn','Params'],[#{method},params]);

This only works if you call that method with something like

(..., "\"myMethod\"", ...)

where you should really passing the name plainly as string.  Makes
usage much simpler and more robust.  So in the method body you then
had

     handle.call(['MethodNameIn','Params'],['#{method}', params]);

Same reasoning applies in other locations such as return_format.

And if you get rid of the no_of_params you can simply use *args and do
not have to go through the hassle generating argument lists.  If may
be though that you want to be able to query arity from the method and
have it fail fast if the argument list does not match in which case
it's OK to generate the argument list.

All in all it seems this is simpler and more redundancy free:

def GET_VALUE(f_name, method, return_format, no_of_params)
  args = no_of_params.times.map {|i| "x#{i}"}.join(", ")

  body = if STUB_CALLS
    %Q{printf("Calling #{method}(#{args}) with parameters <%p>\\n", [#{args}])}
  else
    %Q{
      oai = OA.instance
      handle = oai.getWIN32OLEHandle()
      handle.call(['MethodNameIn','Params'],['#{method}', [#{args}]]);
      ret_val = handle.GetControlValue(#{return_format});
      error = handle.GetControlValue('error out');
      return oai.checkForError(error) ? 'NaN': ret_val
    }
  end

  code = "def #{f_name}(#{args})\n#{body}\nend"
  puts code if ENV['DEBUG'] == 'true'
  class <<self;self;end.class_eval code
end

Cheers

robert


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