Você está na página 1de 22

TRANSFORMATION RULES!

multitarget, multiplatform rendering done easy


- a concept -

Montag, 4. Januar 2010


Multiple targets...

...in files


~/items>
ls
-1
show.*erb




show.de.fbml.erb




show.de.fr.fbml.erb




show.de.fr.html.erb




show.de.fr.iphone.erb




show.de.html.erb




show.de.iphone.erb




show.fbml.erb




show.fr.fbml.erb




show.fr.html.erb




show.fr.iphone.erb




show.html.erb




show.iphone.erb
Montag, 4. Januar 2010
Multiple targets...

...in source




<%
if
current_user.admin?
||
model.ediable?(current_user)
%>






<%
form_for(model)
do
|form|
%>








<%=
:name.t
%><%=
form.input
:name
%>








<%=
:city.t
%><%=
form.input
:city
%>












...






<%
end
%>





<%
else
%>






<div
class='label'><%=
:name.t
%></div>






<div
class='v'><%=h
model.name
%></div>






<div
class='label'><%=
:city.t
%></div>






<div
class='v'><%=h
model.city
%></div>




<%
end
%>

Montag, 4. Januar 2010


What’s the problem?

All view infrastructures need some rules that express


how to create the output data.

Current (as in Rails and Merb) tools are not efficient at


expressing rules. Encourages code duplication, results
in hard to maintain applications.

Montag, 4. Januar 2010


Rails’ MVC problem (I)

• Accessing your models via console, inner-application


etc. takes a different path than via Web servers.
• No ActiveView environment exists. Therefore no
access to helpers.
• Hard to generate HTML outside views.
Or why is number formatting only available in views?

Montag, 4. Januar 2010


Rails’ MVC problem: workarounds

• include Helpers: might or might not work (url_for)


• Fake Controllers
• AbstractController: will be part of Rails 3

Montag, 4. Januar 2010


Rails’ MVC problem (ii)

The interface between controllers and views is


incredibly broad.

• instance variables (especially in partials).


• request info

A tighter interface could help with caching, testing, etc.

Montag, 4. Januar 2010


A better place?

Attach some output converter to your models. After


all: a HTML representation of a model in a specified
context, is still a model representation.

A context object takes the place of the classic controller


object, but without being bound to the HTTP
protocol.

URLs outside HTTP requests: not a problem at all.


Compare URLs in emails.

Montag, 4. Januar 2010


Generating HTML... w/o controller

A very simple HTML generator, that produces nearly


perfect HTML parts. Style the generated HTML to
produce whatever display you want in your browser:

module
SimpleHtml


def
to_html




to_xml.gsub("<",
"<div
class=")


end
end

Don't try this at home: this is no semantic markup. The


generated HTML doesn’t validate.

Montag, 4. Januar 2010


A similar problem domain

CSS: All buttons please with a 2px border in blue.


“delete” buttons, however, get a red border:

div.button
{
border:
2px
solid
blue;
}
div.button.delete
{
border-color:
red;
}

CSS applies a general algorithm to determine the


border.

The actual parameters - width, color, etc. - are supplied


in parts and are assembled depending on how good
an “object address” matches a “rule address”.
Montag, 4. Januar 2010
A general transformation

opts
=
{
:parameter1
=>
value1,
:parameter2
=>
value2
}





tmp
=
preprocess(me,
opts)
tmp
=
render(tmp,
opts)
postprocess
tmp,
opts

A rule set should have entries describing the pre, post,


and render algorithms, and parameters for those.

Montag, 4. Januar 2010


Treat your models DOM-like

Data consists of:

• hash-like, including DataMapper/ActiveRecord


• array-like
• basic types
• ...and unsupported types :)
A DOM needn't be a tree! It must be able to align an
address to its nodes. And it is possible...

Montag, 4. Januar 2010


Defining node names

...quite easily by walking the object structure

node
address
=
parent
address

+
a
node
specific
name
expressing
node
type,
node

position
relative
to
parent.

Montag, 4. Januar 2010


Node name examples

• .<parent hash entity name>: ".name"


• [<parent array position number>]: "[2]"
• basic types: "string", "fixnum"
• arrays, arrays of type T: "array", "users"
• hashes, hashes of type T: "hash", "users"
• object superclass: e.g. "active_record/base"
• object class: e.g. "user"

Beware of circular dependencies.

Montag, 4. Januar 2010


Rule notation

A general rule
<node
name>
<node
name>
...
<node
name>
{


render:
default;
}

Rule scopes
<node
name>
{


<node
name>
...
<node
name>
{




/*
...
*/


}
}

Montag, 4. Januar 2010


Context scopes

Context scopes define context conditions:


• locale,
• target format,
• and more...
target:html
{


/*
rules
*/
}

lang:de
{


/*
rules
*/
}

Montag, 4. Januar 2010


Rules examples (i)

Render strings differently for html and text output:

/*
general
rule
*/
string
{


render:
label
+
":
"
+
me.truncate(truncate);


truncate:
nil;
}

/*
html
rule
*/
:html
string
{


render:
"<span
class='l'>"
+
h(label)
+
":
</span>"
+





"<span
class='v'>"
+
h(me.truncate(truncate))
+
"</span>";
}

Montag, 4. Januar 2010


Rules examples (ii)

Provide label and truncate parameters:

/*
provide
label
*/
user.name
{


label:
"user
name
";
}

/*
truncate
strings
on
iphone
*/
:iphone
string
{


truncate:
80;
}

Montag, 4. Januar 2010


Template rendering

user
{


partial:
"shared/user"


/*





short
for:





render:
render
:partial
=>
"shared/user",
:locals
=>
opts.update(:user
=>
me)


*/
}

Montag, 4. Januar 2010


Context scopes (ii)

Application defined context conditions:


role:guest
.user.name
{


render:
static;


text:
“Register
to
see
user
names”;
}

Default scopes:
/*
two
characters
->
locale
*/
:de
.user.name
{
label:
“Benutzername”;
}

/*
>2
characters
->
target
*/
:fbml
{
/*
facebook
specific
rendering
*/
}

Montag, 4. Januar 2010


Root nodes

Root nodes are useful for pre- and postprocessing

/**
A
quick
and
dirty
PDF
renderer
*/
:pdf
{


/*
:pdf
rules
default
to
:html
rules
*/


@import
:html;





.root
{




post:
html_to_pdf(me);


}



user.name
{
label:
Name
for
PDF;
}
}

Montag, 4. Januar 2010


What’s missing?

• a cool name
• a spec for address weighing
• an example implementation
• a real-life application

http://radiospiel.org

Montag, 4. Januar 2010

Você também pode gostar