straight-shoota / crinja

Implementation of Jinja2 template language in Crystal
https://straight-shoota.github.io/crinja/
Other
127 stars 12 forks source link

Don't want to pass arguments each .render call #32

Closed Dan-Do closed 4 years ago

Dan-Do commented 4 years ago

I already have a site using ecr engine. Now I want to migrate it to use crinja engine. Take an example for this code: name = "Foo"

As far as I know, ecr embed the template string directly to program code. Is it possible to config crinja make it behave as ecr? I want to migrate as least as possible :)

straight-shoota commented 4 years ago

Is it possible to config crinja make it behave as ecr?

Crinja templates are evaluated at runtime. Everything Crinja can see from Crystal land needs to be explicitly exposed. The most common way to do that is binding objects that implement Crinja::Object. An easy helper for this is Crinja::Object::Auto. With ECR I assume you're already using some kind of view type that defines the name property etc. You just need to make that object implement Crinja::Object and bind it to the runtime.

But you actually don't need to pass variable bindings directly to the render method. It will use the current context by default and the method argumens on top. The Crinja environment has a context method which exposes the context. It can also be configured at initialization and using with_context method.

Dan-Do commented 4 years ago

I made it by adding objects/variables to the current context. crinja = Crinja.new ... # now render crinja.context.scope["foo"] = Crinja.value(bar) #or crinja.context.merge! { foo: bar } template = crinja.get_template("login.html") template.render With this I can keep my current syntax. The thing is I have to merge the context every render. Anyway thank you :)

straight-shoota commented 4 years ago

The thing is I have to merge the context every render.

You shouldn't have to do that. Unless you need to assign different values per render? But then you can just assign them directly as arguments to render:

crinja = Crinja.new
crinja.context["variable_for_all_renders"] = Crinja.value(foo)
template = crinja.get_template("login.html")

template.render(variable_for_this_render: Crinja.value(bar)
template.render(variable_for_that_render: Crinja.value(baz)