cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Berin Loritsch <>
Subject [SHRT] Cocoon on Rails Application Component Kernel (CRACK)
Date Fri, 07 Oct 2005 14:09:45 GMT
SHRT = Semi-Humorous Random Thought

Here's the deal: Cocoon is a very powerful publishing framework adapted 
to do web applications, and Ruby on Rails is a very empowering web 
application framework that can be adapted for a number of purposes.  
There are two very different mindsets behind the two frameworks--and I 
believe we can leverage the very potent lessons learned from Rails for 
the Cocoon framework.  The only real humorous aspect of this post is the 
acronym I came up with above.  In one summary statement:

CRACK: A highly adictive web framework that is very potent.  Side 
affects include loss of weight, faster completion, and eagerness for 
more.  Best selling point: seeing the reaction of saying your a "CRACK Ho".

In all seriousness, the biggest lesson from the Ruby on Rails project 
that Cocoon can learn is the power of convention.  One of the biggest 
things that contributes to the high learning curve of Cocoon is the lack 
of convention.  Because there are so many ways of doing things, the user 
has to learn all of them to determine what is going to be best for the 
project the user is working on.  I belive that this lack of convention 
is even a bigger contributor than all the different XML standards that 
we integrate.  A long time ago Stefano gave the RT on the URL as a 
contract--and rightly so.  The Sitemap was born of that RT allowing 
Cocoon to respect the external contract and the developer to organize 
the filesystem any way they chose.  The Rails solution to the problem is 
the convention of the MVC architecture is also mapped in a logical way 
to the files and class structure.  Let me lay out the convention used:

Rails has a definite mapping of the URL to a controller.  The convention 
is {context}/{controller}/{action}[/{id}] where {context} is the 
location where the app is running, {controller} is the controller class 
that responds to actions, {action} is the method on the controller class 
that is called to process a request, and {id} is an optional piece that 
identifies a specific record.  The controller class is defined in the 
app/controllers/ directory and has a naming convention of 
{name}Controller.  For example a "Login" controller would be named 
"LoginController".  Rails finds the controller based on the URL.  Once 
Rails has the controller it calls the method matching the action.  One 
of the side effects is that the URL does not have any extensions defined 
(i.e. there is no .html or .pdf in the URL).  The job of the controller 
is to do any set up for the request before it allows the action to "fall 
through" to the matching view.

The Rails model is one of the most powerful aspects of the whole 
framework.  I'm not going to go into the whole ActiveModel architecture 
other than to say that the model lives in the app/models/ directory and 
the class name is the singular form of the concept (i.e. LogEntry) and 
the backing database table is the plural form (i.e. LogEntries).  Using 
convention to map class methods to tables and records is a very powerful 
aspect that beats out anything else in the Java world.  It would be a 
project in and of itself to write a replacement for this piece--which is 
not something I would recommend for CRACK.

The Rails view lives in app/views/{controller}/{action}.  That's right, 
there is a mapping of a set of views directly 1:1 to the controllers.  
In the case of the LoginController there would be an app/views/login/ 
directory, and for each action ("index", "login" etc.) there would be a 
view that corresponds.  In the Ruby on Rails world these are .rhtml 
files so they are analogous to XSP or JXL files.  In fact I would argue 
that it is closer to JXL than XSP.  Once the method in the controller is 
complete, provided the controller did not explicitly send a named page, 
the view is selected from this directory.  In the CRACK version matching 
the /login/index URL, we would look for (in this order) a .jx file, a 
.xml file, or a .xsp file that matches the name of the action "index".  
More clearly, in that example CRACK would look for 
app/views/login/index.jx first, and then substitute the other extensions 
in case they are there.  The Rails view framework also allows fragments 
that can be embedded in other views, but this is good enough for now.

Now, imagine a Cocoon scenario where the user is faced with a blank 
project.  Where to begin...  Using the power of convention, they start 
writing a class named located in the 
app/controllers/ directory.  They add one method called index() to the 
class.  Then they open the browser to 
http://localhost:8000/cocoon/hello--at which point Cocoon compiles the class and responds by processing the index() method 
(oh yeah, forgot to mention the convention of the index method being the 
default for any controller).  The user sees an error message saying that 
the view app/views/hello/index.jx could not be found.  They realize, 
"Oh, that must be where we process the view".  They add the index.jx 
file in the proper location and retry the URL.  Success!  Relieved and 
happy with the results they start adding more and more functionality 
until they have a wonderfully powerful application.

Where CRACK is Better
Ruby on Rails is highly HTML centric.  That's ok because 80% of all web 
applications are HTML centric.  However, we can leverage a convention 
that they started in a more powerful way.  In addition to the normal 
View conventions, Rails also has the concept of a layout.  You can apply 
the same layout to all the views in your application.  Now, remember 
that I said that Rails doesn't support extensions (.html, .png, etc.).  
We can set up a set of layouts that are essentially the finishing 
pipeline for the application.  By specifying a generic page markup we 
can provide default layouts, but the convention would work like this:

* The layout has a base name such as "site" which is how the layout 
would be specified in the controller.
* The XSLT layout naming convention would be {name}2{ext}.xsl, and we 
would automatically select the serializer mapped to the {ext} name.
  - Example: login/index.html using the "site" layout would transform 
the standard markup using the "site2html.xsl" file and use the "html" 
  - This allows us to also render a "site2pdf.xsl" using the "pdf" 
serializer for /article/show/3.pdf

Changes to Cocoon
In order to support something like this, we don't have to make 
fundamental changes to Cocoon.  In fact, all we have to do is provide an 
alternate Sitemap implementation that uses reflection to find the 
controller class and build the pipeline based on the view source, the 
layout location, etc.  One of the things that would also help _emensely_ 
is to automatically generate a 404 return response if there is no 
Controller/Action match.  There are other things that will help in the 
process, but I believe this is a much more usable way to get baptised 
into Cocoon--and still leverage its power.  Because we would be using 
convention to wire together an application, we have the power to even 
build in some normal conventions for being browser aware by default.  If 
the end client's browser is smart enough to handle client side styling 
then we can let it happen--with no more effort required by the developer.

Oh, and one more thing: we default to UTF-8 as the default encoding all 
the way through.  There are issues with the ESQL logicsheet introducing 
encoding errors, and a few more other locations.  Just because much of 
the commercial industry seems to be ignoring internationalization does 
not mean we should follow they poor example.

What do you think?  Rosy picture?  BTW, I only used the name CRACK as an 
eye catcher--I'm not expecting the final product to be named that.

View raw message