Oops, forgot to return this from a few methods:

public class RubyObjectWrapper {
   private RubyObject foo;
   public RubyObjectWrapper(RubyObject wrapMe, List args) {
       this.foo = wrapMe;
   }
   public Object get(String methodName) {
       return new Builder(methodName, new ArrayList());
   }
   public Object call(String methodName, List args) {
       Object result = foo.callMethod(foo.getRuntime(), methodName,
args.toArray());
       return new RubyObjectWrapper(result);
   }
   public String toString() {
       return this.foo.toString();
   }

   public class Builder {
       private String method;
       private List args;
       public Builder(String method, List args) {
           this.method = method;
           this.args = args;
       }
       public Object with(String arg) {
           this.args.add(arg);
           return this;
       }
       /* just to be fancy... */
       public Object and(String arg) {
           this.args.add(arg);
           return this;
       }
       public Object call() {
           return RubyObjectWrapper.this.call(method, args);
       }
       public String toString() {
           return call().toString();
       }
   }
}



On 2/20/07, Nathan Bubna <[EMAIL PROTECTED]> wrote:
On 2/20/07, Michael <[EMAIL PROTECTED]> wrote:
> How would  the RubyObjectWrapper work when specifying method argument,
> e.g$jrubyObject.testMethod( "argument1", "argument2" ) ?

hmm.  right now, i see only a few options:

a) the wrapper knows what methods it's wrapped object has and
re-implements them itself:
     public Object testMethod(String a, String b) {
        return new RubyObjectWrapper(this.foo.callMethod(
this.foo.getRuntime(), "testMethod", new String[] { a, b }));
     }

    Obviously that means a lot more work on your part and a lot less
flexibility.  But, if you have consistent methods, it may be worth it
for a few of them.

b) you give up the $jrubyObject.testMethod("arg1", "arg2") syntax and
try to find another that's bearable, like
$jrubyObject.call('testMethod', ["arg1", "arg2"])

public class RubyObjectWrapper {
    private RubyObject foo;
    public RubyObjectWrapper(RubyObject wrapMe) {
        this.foo = wrapMe;
    }
    public Object get(String methodName) {
        Object result = this.foo.callMethod(foo.getRuntime(), methodName);
        return new RubyObjectWrapper(result);
    }
    public Object call(String methodName, List args) {
       Object result = this.foo.callMethod(foo.getRuntime(),
methodName, args.toArray());
       return new RubyObjectWrapper(result);
    }
}


c) again, give up the $jrubyObject.testMethod("arg1", "arg2") syntax
and design the wrapper to allow a more natural-language-like interface
such as

   $jrubyObject.testMethod.with("arg1").and("arg2")

this could be done with a wrapper class like:

public class RubyObjectWrapper {
    private RubyObject foo;
    public RubyObjectWrapper(RubyObject wrapMe, List args) {
        this.foo = wrapMe;
    }
    public Object get(String methodName) {
        return new Builder(methodName, new ArrayList());
    }
    public Object call(String methodName, List args) {
        Object result = foo.callMethod(foo.getRuntime(), methodName,
args.toArray());
        return new RubyObjectWrapper(result);
    }
    public String toString() {
        return this.foo.toString();
    }

    public class Builder {
        private String method;
        private List args;
        public Builder(String method, List args) {
            this.method = method;
            this.args = args;
        }
        public Object with(String arg) {
            this.args.add(arg);
        }
        /* just to be fancy... */
        public Object and(String arg) {
            this.args.add(arg);
        }
        public Object call() {
            return RubyObjectWrapper.this.call(method, args);
        }
        public String toString() {
            return call().toString();
        }
    }
}

...or something like that.


> I already start down the road of using an Event handler for InvalidReference
> to catch instances of RubyObject. It works for $jrubyObject.testMethod , but
> I am having the same problem as above, how to handle method arguments? The
> InvalidReferenceEventHandler#invalidMethod does not appear to contain the
> argument information for a reference $jrubyObject.testMethod( "argument1",
> "argument2" )

Perhaps someone else knows a way to get the arg information, but as it
is, i make precious little use of event handlers and don't know.  i
might dig around and see what i can find though.

> thanks,
> Michael
>
> On 2/20/07, Nathan Bubna <[EMAIL PROTECTED]> wrote:
> >
> > I imagine you could get pretty far by wrapping the RubyObjects in a
> > more Velocity-friendly object that takes advantage how Velocity treats
> > get(String) methods before putting it into the context.
> >
> > Perhaps something like:
> >
> >
> > public class RubyObjectWrapper {
> >    private RubyObject foo;
> >    public RubyObjectWrapper(RubyObject wrapMe) {
> >         this.foo = wrapMe;
> >    }
> >    public Object get(String methodName) {
> >         return new RubyObjectWrapper(this.foo.callMethod(
> > foo.getRuntime(), methodName));
> >    }
> > }
> >
> > If i understand the problem space here, this should allow you to
> > traverse the object graph for you RubyObjects as you ask:
> >
> > $jrubyObject.testMethod
> >
> > I'm really not at all familiar with Ruby, much less JRuby, but perhaps
> > this will help you get on the right track.  I use tricks like this to
> > simplify the VTL syntax for various tools in VelocityTools all the
> > time.
> >
> > The other thing which may help here is using Velocity's EventHandler
> > capabilities to recognize when a reference is a RubyObject and treat
> > it differently.   Will is much more experienced and knowledgeable on
> > event handlers than i am, so he may be able to tell you better whether
> > or not that is a dead end for this sort of thing.
> >
> >
> > On 2/20/07, Michael <[EMAIL PROTECTED]> wrote:
> > > Hello,
> > >
> > > I have been using Velocity for years now and find it the best templating
> > > language around. This has lead me to try and spread the joy by
> > attempting to
> > > swap out RHTML for Velocity in JRuby on Rails.
> > >
> > > I have a few simple Ruby test scripts that parse a templates Velocity.
> > > Things get messy when Velocity needs to traverse an object graph. When
> > used
> > > in Rails, the VelocityContext can have a mix of Java objects and
> > RubyObject
> > > (these are the problematic ones).  The RubyObject is a wrapper for a
> > Ruby
> > > object from the JRuby runtime. The RubyObjects do not have static typed
> > > methods, but everything must go through the method 'callMethod'.
> > >
> > > For example, to use velocity notation on the Java object 'sample' to get
> > the
> > > method 'test':
> > >    $sample.test
> > >
> > > would be on a RubyObject 'sample' to get the method 'test':
> > >    $sample.callMethod( $sample.getRuntime(), "test" )
> > >
> > > Things get sticker for passing arguments to a method in RubyObject, all
> > > arguments must implement IRubyObject. I will just skip over this for
> > now.
> > >
> > > Here is the crux of my question,  is it possible to extend Velocity to
> > add
> > > support for handling RubyObjects? Ideally Velocity would be able to
> > > determine whether an object is an implementation of RubyObject, or not,
> > and
> > > handle appropriately, i.e $jrubyObject.testMethod could be call directly
> > > instead of the callMethod for a RubyObject.
> > >
> > >
> > > thanks,
> > > Michael
> > > [EMAIL PROTECTED]
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to