ribbon: an app framework for loop

140 views
Skip to first unread message

Dhanji R. Prasanna

unread,
Aug 11, 2012, 6:27:01 PM8/11/12
to loop...@googlegroups.com
Just been hacking on a little project to benefit Loop. Essentially it is a way to build apps easily with Loop. It is somewhat inspired by Rails/Sinatra and the like.

There are no docs just yet but setting up is pretty straightforward. First you will need to check out and build both Loop and ribbon:

cd loop/
mvn install

cd ribbon/
mvn install
cd bootstrap/
mvn install
cp ../ribbon /usr/local/bin/      # or wherever (this is a tiny script)

Ribbon is built around maven so there is no extra magic going on, or stuff to learn and interop with Java libs is pretty straightforward.

$ mkdir myproj
$ cd myproj
$ ribbon init myproj

   init myproj (new ribbon project)
   create app
   create views
   create assets/images
   create assets/scripts
   create assets/css
    write app/app.loop
    write ribbon.yml
      add org.looplang.ribbon:ribbon-web:1.0      resolving...ok
   update ribbon.yml
  rebuild project classpath
  analyze dependency tree   analyzing...ok
  cleanup temporary files

$ ribbon
Ribbon server started on port: 8080

This creates a project skeleton built mainly for a webapp. As you can see it also adds ribbon-web, which is an event-driven, non-blocking IO web framework similar to Node.js or EventMachine (and built on Netty).

If you navigate to http://localhost:8080 you will see the app running. Edit app.loop and hit refresh in your browser (no restarts/compiles needed!) to see changes.

Take a look at the example app.loop to see what you can do:

(if you specify a route() function you can add additional routes, and spawn to additional loop modules). Jade (Haml-style) templates is also supported.

The nice thing is you can add ANY Java library with a simple step:

$ ribbon add com.google.sitebricks:sitebricks:0.8.6
      add com.google.sitebricks:sitebricks:0.8.6      resolving...ok
   update ribbon.yml
  rebuild project classpath
  analyze dependency tree   analyzing...ok
  cleanup temporary files

This fetches all dependencies (transitively) and updates the project's class path, so the next time your run ribbon, you can use anything from sitebricks (for example, the easy web client).
Note that ribbon remove gets rid of a dep you don't want.

Now, while ribbon comes out of the box with a web framework, there's no reason it needs to be tied to web apps. you can remove ribbon-web and add whatever else you want to create a desktop app, openGL game, or anything you like =)

Do try it out and let me know what you think! It's still a bit raw.

Dhanji. 

Wei Liu

unread,
Aug 11, 2012, 8:49:12 PM8/11/12
to loop...@googlegroups.com
this is great!!!

but I can't find the dependency of jade

:(

Dhanji R. Prasanna

unread,
Aug 11, 2012, 9:03:14 PM8/11/12
to loop...@googlegroups.com
Oops, plz git checkout:

cd jade
mvn install

Wei Liu

unread,
Aug 11, 2012, 11:40:28 PM8/11/12
to loop...@googlegroups.com
there's test failure in jade, so, have to add -Dmaven.test.skip=true to install jade.

BTW, is there any document about how it works?

There is a 'views' folder, I think it's home of jade template files, but don't know how to render them.


Thanks,
Leo

Dhanji R. Prasanna

unread,
Aug 12, 2012, 2:13:41 AM8/12/12
to loop...@googlegroups.com
Hi--can you post the test failure please? It is working for me..

Wei Liu

unread,
Aug 12, 2012, 3:06:24 AM8/12/12
to loop...@googlegroups.com
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.rethrick.jade.SimpleTemplateTest
<!DOCTYPE html>
<html> 
  <head>
    <title>stuff</title>
    <script type="text/javascript">
      //<![CDATA[   
      alert('hi')
      //]]>
    </script>
  </head>
  <body>
    <br/>
    <p id="f" class="doo">foo</p>
    <pbj.doo>
      <!--  This is
         <a>Cooommmmeeennt!</a> -->
      Scrub Kindle! Ren &amp; Stimpy
      <Jade>comment, not emitted.</Jade>
      More text

      <p>Now is: <strong>Cooommmmeeennt!</strong> <em>winter</em> of our poop.</p>
      <em>6</em>

        <yo>1</yo>
        <yo>2</yo>
        <yo>3</yo>
      <div class="doo boo">
          <div id='blah'>sup</div>
      </div>
    </pbj.doo>
  </body> 
  <div id="foot">
    <p>copyright of copies</p>
    &copy; 2011 stuff
  </div>
</html>
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.68 sec <<< FAILURE!

Results :

Failed tests:   toHtml(com.rethrick.jade.SimpleTemplateTest): null expected:<...em date="Thu Jan 01 [10:00:00 E]ST 1970" gate="23">6...> but was:<...em date="Thu Jan 01 [08:00:00 C]ST 1970" gate="23">6...>

Tests run: 3, Failures: 1, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.888s
[INFO] Finished at: Sun Aug 12 15:04:30 CST 2012
[INFO] Final Memory: 5M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.10:test (default-test) on project jade: There are test failures.
[ERROR]
[ERROR] Please refer to /opt/github/jade/target/surefire-reports for the individual test results.
[ERROR] -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.10:test (default-test) on project jade: There are test failures.

Please refer to /opt/github/jade/target/surefire-reports for the individual test results.
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:213)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
Caused by: org.apache.maven.plugin.MojoFailureException: There are test failures.

Please refer to /opt/github/jade/target/surefire-reports for the individual test results.
    at org.apache.maven.plugin.surefire.SurefireHelper.reportExecution(SurefireHelper.java:87)
    at org.apache.maven.plugin.surefire.SurefirePlugin.writeSummary(SurefirePlugin.java:641)
    at org.apache.maven.plugin.surefire.SurefirePlugin.handleSummary(SurefirePlugin.java:615)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:137)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:98)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
    ... 19 more


BTW, I know how to render the jade template now, but how to pass a variable to the jade template ? e.g.

html
    body
        !hello #{name}

Dhanji R. Prasanna

unread,
Aug 12, 2012, 6:04:41 PM8/12/12
to loop...@googlegroups.com
I will check this out but I cannot seem to reproduce =(

To render a template you just return a symbol of the same name (as you probably figured out) as the "view" parameter:

get(req) ->
  { @view: @home }


# in home.jade

html
  body
    p hi there!

The template gets passed the same map, so you can do:

get(req) ->
  { @view: @home,
    @name: 'Clark Kent' }


html
  body
    p hi #{name} from template #{view}.jade

Wei Liu

unread,
Aug 12, 2012, 7:24:59 PM8/12/12
to loop...@googlegroups.com
Seems the jade can only resolve variable in the same line, for instance, the following template works,
html
    body
        p hello, #{name}

however, the next form doesn't work,
html
    body
        p
            | hello, #{name}
the text content can be displayed on the page, but the variable #{name} not resolved.

not sure if this is a bug.

thanks,
Leo

Wei Liu

unread,
Aug 14, 2012, 7:37:56 PM8/14/12
to loop...@googlegroups.com
The root cause is the time zone issue.

in simple.jade
em{ 'date': new java.util.Date(1), 'gate': 23 }= 1 + a

the output will be time zone sensitive, you expect EST in sample_assertion.txt, but I'm in CST.



On Monday, August 13, 2012 6:04:41 AM UTC+8, dhanji wrote:

Dhanji R. Prasanna

unread,
Aug 14, 2012, 8:04:29 PM8/14/12
to loop...@googlegroups.com
ah right of course, that should be an easy fix to convert it to a long. Can you submit a patch? Otherwise I will get to it later in the week.

Wei Liu

unread,
Aug 21, 2012, 8:52:21 PM8/21/12
to loop...@googlegroups.com

Should add ability to support RESTful api, here's my thinking,

instead of :

route(url) =>
  '/' : ...
  '*' : ...

it's better to have :

route(method, url) =>
  @get, '/' : ...
  @post, '/account' : ...
  @get, '/account/@{name}' : @findAccount

the problem above is how to support parameter with pattern matching.

Thoughts / comments?

Leo

On Sunday, August 12, 2012 6:27:01 AM UTC+8, dhanji wrote:

Dhanji R. Prasanna

unread,
Aug 21, 2012, 9:16:49 PM8/21/12
to loop...@googlegroups.com
Interesting. I took a more or less RESTful API (similar to Sinatra/Rails). The idea is:

- there is a "resource" module for each URL path. Example /product -> product.loop
- you define get(), put(), post() etc., once in product.loop and similarly for each URL path

So in your example, route would look like:

route(uri) =>
  '/account' : @account

in account.loop:

get(req) ->
  ..

post(req) ->
  ..

etc.




For parameters you can definitely match using regexes:


route(uri) =>
  /\/account\/.+/ : @account
 

Or you can use guards for branching (not as nice maybe):

route(uri) =>
  ('/account/' + subpath) |  subpath == 'list' :  @account_list
                                   |  subpath.startsWith('id/') :  @account

etc.

You can also return functions directly from route (which will handle all of GET, PUT, POST ,etc.), maybe this was confusing?

sekaran6

unread,
Aug 28, 2012, 8:38:22 AM8/28/12
to loop...@googlegroups.com
Dear Sir, 
Please consider supplying Jade and Ribbon also as a binary distribution as Loop.After checking out when I try to build with Maven 3, I get only Build Failures.
In the case of loop the message was 

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2

<default-test> on project loop: There are test failures.

For Jade

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.

<default-test> on project jade: There are test failures.

for ribbon

Failed to execute goal on project ribbon-web: Could not resolve dependencies for project org.looplang:llop:jar:1.0, com.rethink:jade:jar:1.0:could not find artifact org.looplang:loop:jar:1.0 in jboss-maven-repository (http”//repository.jbosss.org/nexus/content/repositories/releases.

sekaran

Dhanji R. Prasanna

unread,
Aug 28, 2012, 12:40:17 PM8/28/12
to loop...@googlegroups.com
Yea as I said you have to build these yourself right now. It is just for alpha testing. We will eventually release to maven central etc.
Reply all
Reply to author
Forward
0 new messages