Backbone.js with Eco Templates: How to include template within a template? - ruby-on-rails

Is it possible to include a template within a template? Maybe something similar to the way ERB handles partials?
Rather than attempting to render nested models in a fashion like ERB, it's better to let Backbone.js take care of this.
Note, I am using coffeescript syntax:
Projects.IndexView
template: JST["backbone/templates/projects/index"]
addAll: () ->
#options.projects.each(#addOne)
addOne: (project) ->
view = new Worktimer.Views.Projects.ProjectView({model : project})
#$("#projects-table").append(view.render().el)
render: ->
$(#el).html(#template(projects: #options.projects.toJSON() ))
#addAll()
the model Project has a nested collection called sessions:
Projects.ProjectView
template: JST["backbone/templates/projects/project"]
$(#el).html(#template(#model.toJSON() ))
for s in #model.sessions.models
v = new Worktimer.Views.ProjectSessions.ShowView(model: s)
$(#el).find('.sessions').append(v.render().el)
ProjectSessions.ShowView
template: JST["backbone/templates/project_sessions/show"]
render: ->
$(this.el).html(#template(#model.toJSON() ))
so, in the end we have nested templates like this:
Projects Index
Project
Session
Session
Session
Session
Project
Session
Project
Session
Session

here a little helper I use for spine:
# Render Partials in ECO-Templates like in Rails-ERB
#
# usefull to clean up structure in spine.js and other js-mvc´s like backbone
#
# usage:
# <%- render_partial 'path/to/partial' %> .. will render ../spine-app/views/path/to/_partial.jst.eco
# <%- render_partial 'path/to/partial', foo: 'bar' %> .. will render ../spine-app/views/path/to/_partial.jst.eco .. locals = #foo
#
window.render_partial = ( path, options = {} ) ->
# add the leading underscore (like rails-partials)
path = path.split('/')
path[ path.length - 1 ] = '_' + path[ path.length - 1 ]
path = path.join('/')
# render and return the partial if existing
try
JST["app/views/#{ path }"]( options )
catch error
# if App.Environment != 'production' then "<p class='error'>Sorry, there is no partial named '#{ path }'.</p>" else ''
"<p class='error'>Sorry, there is no partial named '#{ path }'.</p>"

I don't think Eco supports this. It's intended more as a simple templating system like Mustache than as a full-fledged ERB replacement. On Rails, you'd probably render an Eco template and inject the output into an ERB or Haml template.
For Node.js development, you might want to take a look at CoffeeKup, which lets you do your templating in CoffeeScript and supports partials.

If you prefix the template with .erb, you can use the ERB processor.
Change yourfile.js.coffee to yourfile.js.coffee.erb, then you'll be able to add <%= %> tags to your CoffeeScript template.

Related

Using mustache templates as partial views in Rails 4?

I'm trying to use mustache views in Rails 4 instead of some old partial views that hosted some HTML templates I am sharing with a javascript application.
Added config/initializers/mustache.rb
# Tell Rails how to render mustache templates
module MustacheTemplateHandler
def self.call(template)
#assigns contains all the instance_variables defined on the controller's view method
"Mustache.render(#{template.source.inspect}, assigns).html_safe"
end
end
# Register a mustache handler in the Rails template engine
ActionView::Template.register_template_handler(:mustache, MustacheTemplateHandler)
I named my template _template.mustache and put it the template in views/sales/_template.mustache and I can render it just fine from normal .html.erb with render partial: 'template'
Where do I put the Template.rb file for it to work with the mustache?
class Template < Mustache
def something
# return something
"WOW"
end
end
So, you can write this variables directly to yours controller.

Output slim to variable

I'm using Base64.encode64(val) to convert html to base64.
Example:
- val = link_to 'Link', link_path
= Base64.encode64(val)
But how can I get slim markup to variable? Like so:
.class = link_to 'Link', link_path # <- this output with slim div
Or even multiple lines
div
span
.another_div
There is a way by putting slim code into partial and do this:
- var = render 'partial'
= Base64.encode64(var) # Convert into base64
How to do this without partial?
Slim exposes its templating through the Tilt interface, like so:
# Render a template file:
Slim::Template.new("template.slim", options).render(scope)
# Render a string:
Slim::Template.new(options) { "b slim markup" }.render(scope)
Where options is an optional hash of options for slim and scope is the object in which the template code is executed.
So the following:
slim_markup = <<-SLIM
div
span
.another_div
SLIM
# The options hash and scope have been omitted for the sake of simplicity
html_output = Slim::Template.new { slim_markup }.render
Sets the value of html_output to:
<div></div>
<span></span>
<div class="another_div"></div>
But for your example with the url helper link_path, you must provide slim a scope in which the url helpers are available e.g. a controller.
This is an old question, but I have wondered about this many times, and I always spend a lot of time researching it.
Using Slim 4 you can use capture directly:
- val = capture
div
span
.another_div
This will put the rendered slim into your variable.
Another way from the box using capture method. From the docs:
Using the Binding you can capture to local variables as follows:
module Helpers
def capture_to_local(var, &block)
set_var = block.binding.eval("lambda {|x| #{var} = x }")
# In Rails we have to use capture!
# If we are using Slim without a framework (Plain Tilt),
# you can just yield to get the captured block.
set_var.call(defined?(::Rails) ? capture(&block) : yield)
end
end
The helper can then be used in the Slim template as follows
/ The captured_content variable must be known by the Binding beforehand.
= capture_to_local captured_content=:captured_content
p This will be captured in the variable captured_content
= captured_content
Read more https://github.com/slim-template/slim#capturing-to-local-variables

Rebuild Haml assets in development

I'm working on an angular project and I'm using the angular-rails-templates gem to manage the templates. I have a custom method in rails in order to create 'partials' between my templates.
module HamlHelper
def include_partial(partial, locals = {})
Haml::Engine.new(File.read("#{Rails.root.to_s}/app/assets/javascripts/#{partial}")).render(Object.new, locals)
end
end
So that I can have in my haml templates for example:
/assets/javascripts/templates/page1.html.haml
- header = { title: 'Page 1'}
.page
= include_partial 'shared/header.html.haml', locals: header
...
and
/assets/javascripts/shared/header.html.haml
%header.header
.header__container
%h1.header__title= locals[:title]
...
The problem I'm having is that if I want to modify the header.html.haml partial, the changes are only updated when I modify the page1.html.haml file which contains the partial. So since page1 is not modified, Rails thinks that it wasn't modified and then page1 is not processed again. Is there a solution for this?
NOTE: I used here a very basic example for my partial, but in reality is a more complex one. So using ng-include of angular is not what I need.

Embedding an ejs template inside of an erb template

I'm building a javascript-heavy rails 3 app. It uses underscore.js, which has a very elegant templating mechanism built on top of ejs ( http://embeddedjs.com/).
The problem: embeddedjs borrows heavily from the erb syntax, so including ejs templates in an erb template causes rendering problems with the view.
Is there a way to include "non-erb" sections in an erb file? This would let me define ejs templates inside erb files. Right now I'm using a hack where I have a helper that reads the raw contents of a file containing ejs templates, and outputting that as a raw string in the erb template.
I use this trick to solve the problem:
// Using custom tags to be able to use regular for templates in templates
var ejs = require('ejs');
ejs.open = '{{';
ejs.close = '}}';
// Using html extension for custom ejs tags
app.register('.html', ejs);
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
This changes <% %> to {{ }}, and let me use <% %> for templates which are used by JS. This works for me as I don't have classic style templates (<% %>).
If you have a lot of those you may want to do the same trick but for underscore.js templates.
You could save ejs as a seperate file and than render it as a text (which won't be evaluated as erb) inside script tag.
Inside your erb partial:
<script id="my_awesome_template" type="text/x-ejs">
<%= render :text => File.open("app/views/controller_name/_my_awesome_template.html.ejs").read %>
</script>`
In your JavaScript file:
new EJS({element: document.getElementById('my_awesome_template')}).render(data)
Escape your Underscore variables: (The ones you do not want erb to interpolate)
<%= foo %> becomes:
<%%= foo %>

render_to_string in lib class not working

I'm trying to use delayed_job to update a remote database via xml
In my lib folder I put a file with a class that should do a render_to_text with template.xml.builder, but I get:
undefined method `render_to_string' for #<SyncJob:0x7faf4e6c0480>...
What am I doing wrong?
ac = ActionController::Base.new()
ac.render_to_string(:partial => '/path/to/your/template', :locals => {:varable => somevarable})
I had problems with a undefined helper method then I used ApplicationController
ApplicationController.new.render_to_string
render_to_string is defined in ActionController::Base. Since the class/module is defined outside the scope of the Rails controllers the function is not available.
You are going to have to manually render the file. I don't know what you are using for your templates (ERB, Haml, etc.). But you are going to have load the template and parse it yourself.
So if ERB, something like this:
require 'erb'
x = 42
template = ERB.new <<-EOF
The value of x is: <%= x %>
EOF
puts template.result(binding)
You will have to open the template file and send the contents to ERB.new, but that an exercise left for you. Here are the docs for ERB.
That's the general idea.
Rails 5
render_to_string and others are now available as class methods on the controller. So you may do the following with whatever controller you prefer: ApplicationController.render_to_string
I specifically needed to assign a dynamic instance variable for the templates based on an object's class so my example looked like:
ApplicationController.render_to_string(
assigns: { :"#{lowercase_class}" => document_object },
inline: '' # or whatever templates you want to use
)
Great blog post by the developer who made the rails PR: https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions
You could turn your template.xml.builder into a partial (_template.xml.builder) and then render it by instantiating an ActionView::Base and calling render
av = ActionView::Base.new(Rails::Configuration.new.view_path)
av.extend ApplicationController.master_helper_module
xml = av.render :partial => 'something/template'
I haven't tried it with xml yet, but it works well with html partials.

Resources