Forum: JRuby scriptingContainer callMethod question

Posted by Robin McKay (robin2)
on 2013-01-27 13:05
I can get scriptingContainer to call methods in my JRuby file but not if
the method is within a class.

For example if the file contains

   def onActivityResult(a,b,c)
      # do something
   end

or an alternative version

   def startmeup
      tt = Testclass.new
   end

   class Testclass

    def onActivityResult(a,b,c)
          # do something
    end

   end

The first version that is not in the class works fine but I can't figure
out how (or if) scriptingContainer can call the method inside the class
in the second version.

Thanks

...R
Posted by Gergely Nagy (Guest)
on 2013-01-27 13:45
(Received via mailing list)
Please paste your actual scriptingContainer.callMethod(...) invocation.
Posted by Robin McKay (robin2)
on 2013-01-27 15:20
I don't know what this is going to achieve - because it works properly
with the first version of my JRuby code and I don't know how to
configure it for the second version ... but here it is (ignore the crude
log messages)

    @Override
     public void onActivityResult(int requestCode, int resultCode,
Intent data)
     {
      Log.e("SOMETHING", "here we are in onActivityResult");
      String method = "onActivityResult";
      Object[] args = new Object[3];
      args[0] = requestCode;
      args[1] = resultCode;
      args[2] = data;
      Log.e("SOMETHING", "here we are 2 onActivityResult");
      container.callMethod(receiver, method, args, Double.class);
     }

Do you know if it is possible to use scriptingContainer to call a method 
within a class?

...R


>Gergely Nagy wrote in post #1093957:
> Please paste your actual scriptingContainer.callMethod(...) invocation.
Posted by Keith B. (keith_b)
on 2013-01-27 18:52
(Received via mailing list)
Robin -

How are you getting your receiver object?  Here's an example from an 
article at http://java.dzone.com/articles/integrating-jruby-and-java:

Object greeter = container.runScriptlet("CustomerClassSelector.new");
String customerClass = container.callMethod(greeter, "choose_class", 
loyaltyPoints, String.class);

- Keith

---
Keith R. Bennett
http://about.me/keithrbennett
Posted by Gergely Nagy (Guest)
on 2013-01-27 20:29
(Received via mailing list)
>
> I don't know what this is going to achieve


It would just make your question a bit specific, so as to help us answer 
it.
Obviously what is interesting is not what variable you pass receiver in,
but what the value is.

As Keith suggests, if the receiver is the result of "Testclass.new" or
"startmeup" then you're on the right track.
Posted by Robin McKay (robin2)
on 2013-01-28 10:00
Thanks Keith and Gergely,

Jeez - I thought this was a simple question...

At the moment I have two methods in my Java code (it's for an Android 
device). With onCreate() I start the script with

   receiver = container.runScriptlet(PathType.CLASSPATH, filename)
   String method = "startMeUp";
   container.callMethod(receiver, method);

"filename" is the name of my JRuby file.

then I use the same receiver in the second method onActivityResult() but 
changing the name of the JRuby method to be called.

As I said in my original post this all works fine as long as the methods 
in the JRuby file aren't enclosed in a class - and I can live with that 
if that's the way things must be.

I have tried a version of my code in which all but the "startmeup" 
method is enclosed in a class and "startmeup" includes the code

   @jj = Myclass.new
   @jj.setup

Then I would like to be able to call directly from Java into the class

   @jj.onActivityResult(a,b,c)

I'm afraid I can't figure out your example and the link is broken.

First, is "CustomerClassSelector" the name of a variable from somewhere 
else or is it an indicator of something I should replace with my own 
variable, and if so what sort of thing would it be?

Second, what does the ".new" part of CustomerClassSelector do? and where 
does it do it? If it is an initialize of a JRuby class does this mean 
that the class is initialized every time the scriplet is run, and if so 
how do you maintain JRuby instance variable between calls.

Perhaps I should make it clear that the calls to JRuby are NOT for the 
purpose of returning info to the Java program. I want everything to 
happen in JRuby and the Java is just an unavoidable irritant to pick up 
Android callbacks and pass them on to JRuby and I want to minimize the 
Java.

Also, to head off any digression, this is a scriptingContainer question, 
not an Android question. If someone can explain how to do what I want 
with regular Java I can check if it works on Android.

Again, Thanks

...R

>Keith B. wrote in post #1093974:
> Robin -
>
> How are you getting your receiver object?  Here's an example from an
> article at http://java.dzone.com/articles/integrating-jruby-and-java:
>
> Object greeter = container.runScriptlet("CustomerClassSelector.new");
> String customerClass = container.callMethod(greeter, "choose_class",
> loyaltyPoints, String.class);
>
> - Keith
>
> ---
> Keith R. Bennett
> http://about.me/keithrbennett
Posted by Gergely Nagy (Guest)
on 2013-01-28 13:55
(Received via mailing list)
>
> Jeez - I thought this was a simple question...


Yeah, it should have been simple, you just missed 1 simple necessary 
detail
to be able to help you (while getting a lot of unnecessary ones).
You found a method wasn't working, and I was simple asking how you call
that method.

Also, to head off any digression, this is a scriptingContainer question

Action, this question doesn't seem specific to ScriptingContainer or
even JRuby (or Android, as you said). It's more about "how to instance
method in Ruby?"

Therefore the best is to understand a bit more of Ruby object model, eg 
see
 http://www.ruby-doc.org/docs/ProgrammingRuby/html/....

So the simple answer to your simple question would be "to be able to 
call a
method,  first you need an object for it that can handle it". I assume 
that
would not make you happier, so I'll try to clarify further.

The idea is to send a message to the receiver, where *receiver* is an
object which knows how to handle it and respond (in the lucky case).
What messages an *object* can handle depends on the *methods* defined in
its *class* (there's more to that, but let's keep it simple now).
You create an object of a class named CustomerClassSelector, by calling
.new method on the class (to answer your other question).

In your first attempt, you just defined a method on the class named
"Object" (the default place for top-level method).
Since this is the root of the class hierarchy all objects will have your
method.
IOW it does not matter what the receiver object is in your first case,
hence it works.

In your second one, you're defining the method within a TestClass, so it
will be only available in objects of TestClass.
That's why we were asking what your receiver object is.

I use the same receiver in the second method onActivityResult()

This is probably wrong, if I understand your snippets your receiver 
object
is *not* a TestClass -in fact it's probably a nil (which is an object of
NilClass).

Again, what you probably should do is the set the receiver there to the
result of "startmeup" , in this case the result of the first callMethod.
In pure Ruby, this would be
mytest = startmeup()
mytest.onActivityResult(..)

hope this helps,
Gergo
Posted by Robin McKay (robin2)
on 2013-01-28 21:11
Thanks Gergo, that has enabled me to get it working.

In the first method I now have

   receiver = container.runScriptlet(PathType.CLASSPATH, filename)
   String method = "startMeUp";
   theClass = container.callMethod(receiver, method, Object.class);

and in the JRuby code the method "startMeUp" returns the class instance
it has created

and in the second method I have

    container.callMethod(theClass, method, args, Double.class);

------------


>Gergely Nagy wrote in post #1094052:
>>
>> Jeez - I thought this was a simple question...
>
>
> Yeah, it should have been simple, you just missed 1 simple necessary
> detail
> to be able to help you (while getting a lot of unnecessary ones).
> You found a method wasn't working, and I was simple asking how you call
> that method.

No, I had no non-working method because I didn't even know how to get
that far when the JRuby method was in a class.

> Also, to head off any digression, this is a scriptingContainer question
>
> Action, this question doesn't seem specific to ScriptingContainer or
> even JRuby (or Android, as you said). It's more about "how to instance
> method in Ruby?"

The solution has shown that this was completely a ScriptingContainer
question - none of the documentation I have read has even hinted that
ScriptingContainer can be used like this. What other useful secrets has 
it got?

> Therefore the best is to understand a bit more of Ruby object model, eg
> see
>  http://www.ruby-doc.org/docs/ProgrammingRuby/html/....
>
> So the simple answer to your simple question would be "to be able to
> call a
> method,  first you need an object for it that can handle it". I assume
> that
> would not make you happier, so I'll try to clarify further.
>
> The idea is to send a message to the receiver, where *receiver* is an
> object which knows how to handle it and respond (in the lucky case).
> What messages an *object* can handle depends on the *methods* defined in
> its *class* (there's more to that, but let's keep it simple now).
> You create an object of a class named CustomerClassSelector, by calling
> .new method on the class (to answer your other question).

Yes, I already knew this as it applied to regular JRuby.

> In your first attempt, you just defined a method on the class named
> "Object" (the default place for top-level method).
> Since this is the root of the class hierarchy all objects will have your
> method.
> IOW it does not matter what the receiver object is in your first case,
> hence it works.
>
> In your second one, you're defining the method within a TestClass, so it
> will be only available in objects of TestClass.
> That's why we were asking what your receiver object is.

I understand now, but I would have liked it if you had explained your 
question.

> I use the same receiver in the second method onActivityResult()
>
> This is probably wrong, if I understand your snippets your receiver
> object
> is *not* a TestClass -in fact it's probably a nil (which is an object of
> NilClass).
>
> Again, what you probably should do is the set the receiver there to the
> result of "startmeup" , in this case the result of the first callMethod.
> In pure Ruby, this would be
> mytest = startmeup()
> mytest.onActivityResult(..)
>
> hope this helps,

Yes it has, thanks again

> Gergo
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.