Inspecting a block given to a method

T

Thomas Mueller

Hi,

I am using JRuby to access data in some business application (Siebel,
if anybody is interested).
In Siebel I need to activate fields if I want to access them later:

bc.activate_field(name)
bc.query(search_specs)
do stuff

I've written methods that do the query and then yield each record to a
given block, so I can write something like:

bc.activate_field("field1")
bc.activate_field("field2")
bc.find_all(search_specs) do |record|
record["field1"] = "some value"
puts record["field2"]
end

I would like to do the activate_field() calls automatically, based on
which fields are being accessed inside the block.
Is it possible to look into the block and find out which fields are
being accessed? In the above example that would include the fields
"field1" and "field2".
Basically, can I access the code inside the block and inspect it?

Thomas
 
C

Christopher Dicely

Hi,

I am using JRuby to access data in some business application (Siebel,
if anybody is interested).
In Siebel I need to activate fields if I want to access them later:

bc.activate_field(name)
bc.query(search_specs)
do stuff

I've written methods that do the query and then yield each record to a
given block, so I can write something like:

bc.activate_field("field1")
bc.activate_field("field2")
bc.find_all(search_specs) do |record|
record["field1"] = "some value"
puts record["field2"]
end

I would like to do the activate_field() calls automatically, based on
which fields are being accessed inside the block.
Is it possible to look into the block and find out which fields are
being accessed? In the above example that would include the fields
"field1" and "field2".
Basically, can I access the code inside the block and inspect it?


I don't know of any way to do that. But I don't think you need to:
you can yield a proxy object to the block that intercepts the
references (the []= methods on the record object, or anything else
that requires activation) and activates fields as necessary, before
passing the call on to the object that does the real work, I think.
 
T

Thomas Mueller

Thanks for your quick reply. If I understand you correctly that would
result in something like this being executed:

bc.find_all(search_specs) do |record|
activate("field1") # this is what the proxy object would do
record["field1"] = "some value"
activate("field2") # this is what the proxy object would do
puts record["field2"]
end

That wouldn't work because the fields need to be activated before I
query the data, basically before or at the beginning of the find_all()
method.

When I query for data in Siebel it issues SQL statements to the
database and only includes activated fields. Activating fields just
before accessing them doesn't work - they need to be activated before
querying the database.

My find_all() looks something like this:

def find_all
self.clear_to_query()
self.set_search_spec(...) # several of those, based on arguments to find_all()
self.execute_query()

begin
yield self
end while self.next_record() if self.first_record()
end

The fields need to be activated before the execute_query() call.

Thomas


2008/3/5 said:
Hi,

I am using JRuby to access data in some business application (Siebel,
if anybody is interested).
In Siebel I need to activate fields if I want to access them later:

bc.activate_field(name)
bc.query(search_specs)
do stuff

I've written methods that do the query and then yield each record to a
given block, so I can write something like:

bc.activate_field("field1")
bc.activate_field("field2")
bc.find_all(search_specs) do |record|
record["field1"] = "some value"
puts record["field2"]
end

I would like to do the activate_field() calls automatically, based on
which fields are being accessed inside the block.
Is it possible to look into the block and find out which fields are
being accessed? In the above example that would include the fields
"field1" and "field2".
Basically, can I access the code inside the block and inspect it?



I don't know of any way to do that. But I don't think you need to:
you can yield a proxy object to the block that intercepts the
references (the []= methods on the record object, or anything else
that requires activation) and activates fields as necessary, before
passing the call on to the object that does the real work, I think.
 
C

Christopher Dicely

Thanks for your quick reply. If I understand you correctly that would
result in something like this being executed:


bc.find_all(search_specs) do |record|
activate("field1") # this is what the proxy object would do
record["field1"] = "some value"
activate("field2") # this is what the proxy object would do
puts record["field2"]
end

That wouldn't work because the fields need to be activated before I
query the data, basically before or at the beginning of the find_all()
method.

When I query for data in Siebel it issues SQL statements to the
database and only includes activated fields. Activating fields just
before accessing them doesn't work - they need to be activated before
querying the database.

My find_all() looks something like this:

def find_all
self.clear_to_query()
self.set_search_spec(...) # several of those, based on arguments to find_all()
self.execute_query()

begin
yield self
end while self.next_record() if self.first_record()
end

The fields need to be activated before the execute_query() call.

Hmm. That's trickier. You could create an method on some convenient class
(or object) from the block with define_method, and then use ParseTree to get
the parse tree of that method, and walk through the resulting s-expression to
find out which fields are called. Though if any of the fields are determined
dynamically, that won't work, because you won't have the results of the
dynamic determination, just the parse tree of the code that would get it.

(My ParseTree-fu isn't strong enough to sketch out code to demonstrate that,
but conceptually, with the caveat about dynamic determination of fields,
it seems at least possible.)
 
W

William James

Thomas said:
Hi,

I am using JRuby to access data in some business application (Siebel,
if anybody is interested).
In Siebel I need to activate fields if I want to access them later:

bc.activate_field(name)
bc.query(search_specs)
do stuff

I've written methods that do the query and then yield each record to a
given block, so I can write something like:

bc.activate_field("field1")
bc.activate_field("field2")
bc.find_all(search_specs) do |record|
record["field1"] = "some value"
puts record["field2"]
end

I would like to do the activate_field() calls automatically, based on
which fields are being accessed inside the block.
Is it possible to look into the block and find out which fields are
being accessed? In the above example that would include the fields
"field1" and "field2".
Basically, can I access the code inside the block and inspect it?

Thomas

bc.find_all(search_specs,'field1','field2') { |record,fields|
record[field[0]] = "some value"
puts record[field[1]]
}
 
W

William James

Thomas said:
I am using JRuby to access data in some business application (Siebel,
if anybody is interested).
In Siebel I need to activate fields if I want to access them later:
bc.activate_field(name)
bc.query(search_specs)
do stuff
I've written methods that do the query and then yield each record to a
given block, so I can write something like:
bc.activate_field("field1")
bc.activate_field("field2")
bc.find_all(search_specs) do |record|
record["field1"] = "some value"
puts record["field2"]
end
I would like to do the activate_field() calls automatically, based on
which fields are being accessed inside the block.
Is it possible to look into the block and find out which fields are
being accessed? In the above example that would include the fields
"field1" and "field2".
Basically, can I access the code inside the block and inspect it?

bc.find_all(search_specs,'field1','field2') { |record,fields|
record[field[0]] = "some value"
puts record[field[1]]}

A couple of s's were missing.

bc.find_all(search_specs,'field1','field2') { |record,fields|
record[fields[0]] = "some value"
puts record[fields[1]]}
 
T

Thomas Mueller

I think that'll be sufficient. My goal is to make it easy for the user
(which is mainly myself) to be lazy :) and activate the fields
automatically. If I can't capture the usage of some fields sometimes
then those fields can still manually be activated.
I'm already installing ParseTree and will try that out. Looks promising.

Thanks a lot.
 
T

Thomas Mueller

2008/3/5 said:
bc.find_all(search_specs,'field1','field2') { |record,fields|

record[fields[0]] = "some value"
puts record[fields[1]]}
That would work but the user would still have to identify the fields
that need to be activated. I'd rather have that done automatically.

Thanks anyways.
 
J

John Wilger

Thanks for your quick reply. If I understand you correctly that would
result in something like this being executed:

bc.find_all(search_specs) do |record|
  activate("field1")  # this is what the proxy object would do
  record["field1"] = "some value"
  activate("field2")  # this is what the proxy object would do
  puts record["field2"]
end

That wouldn't work because the fields need to be activated before I
query the data, basically before or at the beginning of the find_all()
method.
My find_all() looks something like this:

def find_all
  self.clear_to_query()
  self.set_search_spec(...) # several of those, based on arguments to find_all()
  self.execute_query()

  begin
    yield self
  end while self.next_record() if self.first_record()
end

You could instead yield to the given block /before/ doing the actual
query and pass in an object which would simply record the method
calls. Then you could figure out the fields that need to be activated
from that, do the query, and replay the method calls on the actual
records returned. This would get difficult if you tried to do anything
beyond basic one-liners within the block, but it might work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top