> --
> You received this message because you are subscribed to the Google Groups "play-framework" group.
> To post to this group, send email to play-fr...@googlegroups.com.
> To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.
>
>
--
Guillaume Bort, http://guillaume.bort.fr
Probably a better (and simpler) start for you, here is my test to make
Scalate work with the current Play version (my test use Jade):
https://gist.github.com/1184490
All you need is to drop scalate-core and scalate-utils jars into the
lib directory of your application (or add them as managed dependencies
to the yaml file).
There is no clean error report yet, but it should be really easy to
add for compilation errors since they already contain the problem
position. Not sure how difficult it will be to report properly
execution errors.
I was able to use this example to get things working.
Improvements I'd like to see:
1. Allow the Scalate syntax to be configurable.
I did this with the following in Scalate:
case class Template(name: String) {
val scalateType = "." + Play.configuration.get("scalate");
def render(args: (Symbol, Any)*) = {
scalateEngine.layout(name + scalateType, args.map {
case (k, v) => k.name -> v
} toMap)
}
}
2. Like regular templates, change things so def index {} in Application can have something like the following:
def index = {
render('user -> User("Guillaume"))
}
And "Application/index" will be passed into the Scalate constructor. What's the best way to do this? Create a ScalateController that overrides render() and is able to introspect the class/method names?
Thanks,
Matt
Yes, but you should use a Trait instead, so it's easier to mix several
concerns into your controller.
object Application extends Controller with Scalate {
...
}
> How would I go about modifying things so I can have a method like the
> following?
>
> def sayHello(name: String) = {
> render(name)
> }
>
In Java, this feature relies on heavy bytecode manipulation that we
have disabled for Scala. In theory for your simple use case it could
work, but Scala is way more complicated and there is a lot of
constructs where it would not be possible to track local variable
names properly.
> In my Jade template, I'd also like to simplify and not have to define
> "name" as a variable. Currently, I have to have the following in
> sayHello.jade:
>
> -@ var name: String
> p Hi #{name: String}
I don't know if it is possible with Scalate? If yes, there should be a
configuration setting to set somewhere on the TemplateEngine.
The next issue I'm running into is running it in prod mode. Is there any way to stop Groovy from trying to compile my Jade templates?
$ play run
~ _ _
~ _ __ | | __ _ _ _| |
~ | '_ \| |/ _' | || |_|
~ | __/|_|\____|\__ (_)
~ |_| |__/
~
~ play! 1.2.3, http://www.playframework.org
~
~ Ctrl+C to stop
~
16:49:32,968 INFO ~ Starting /Users/mraible/dev/play-more
16:49:32,973 INFO ~ Module coffee is available (/Users/mraible/dev/play-more/modules/coffee-1.0)
16:49:32,974 INFO ~ Module scala is available (/opt/tools/play-1.2.1/modules/scala-0.9.1)
16:49:34,492 INFO ~ Scala support is active
16:49:34,642 INFO ~ Scala support is active
16:49:34,643 INFO ~ Precompiling ...
Compiling:
/Users/mraible/dev/play-more/modules/coffee-1.0/app/tags/CoffeeTags.java
16:49:37,491 ERROR ~
@67iec0he2
Cannot start in PROD mode with errors
Template compilation error (In /app/views/Application/index.jade around line 2)
The template /app/views/Application/index.jade does not compile : #{user.name} is not closed.
play.exceptions.TemplateCompilationException: #{user.name} is not closed.
at play.templates.TemplateCompiler.generate(TemplateCompiler.java:102)
at play.templates.TemplateCompiler.compile(TemplateCompiler.java:15)
at play.templates.GroovyTemplateCompiler.compile(GroovyTemplateCompiler.java:41)
at play.templates.TemplateCompiler.compile(TemplateCompiler.java:26)
at play.templates.TemplateLoader.load(TemplateLoader.java:82)
at play.templates.TemplateLoader.scan(TemplateLoader.java:222)
at play.templates.TemplateLoader.scan(TemplateLoader.java:235)
at play.templates.TemplateLoader.scan(TemplateLoader.java:235)
at play.templates.TemplateLoader.getAllTemplate(TemplateLoader.java:205)
at play.Play.preCompile(Play.java:570)
at play.Play.init(Play.java:291)
at play.server.Server.main(Server.java:158)
override def loadTemplate(file:VirtualFile )
def populateRenderArgs(args: (Symbol, Any)*) = {
val renderArgs = Scope.RenderArgs.current();
args.foreach {
o =>
renderArgs.put(o._1.name, o._2)
}
renderArgs.put("session", Scope.Session.current());
renderArgs.put("request", Http.Request.current());
renderArgs.put("flash", Scope.Flash.current());
renderArgs.put("params", Scope.Params.current());
renderArgs.put("errors", Validation.errors());
}
Then I call it from my Template class and convert the RenderArgs map to a Scalate friendly map.
case class Template(name: String) {
import scala.collection.JavaConversions._
def render(args: (Symbol, Any)*) = {
populateRenderArgs(args: _*)
val convertedArgs: Map[String, Any] = Scope.RenderArgs.current().data.toMap
val argsMap = convertedArgs.map {
case (k, v) => k -> v
}.toMap
scalateEngine.layout(name + scalateType, argsMap)
}
}
This allows me to do things like get parameters in a Jade template:
-@ val params: play.mvc.Scope.Params
{params.get('foo')}
If I pass in http://localhost:9000?foo=bar, it'll render "bar".
I'd love it if there was a shortcut where I could write {params.foo} like you can with JSTL.
Please let me know if you think there's anything I could improve.
Thanks,
Matt