Skip to content

Instantly share code, notes, and snippets.

@simeonwillbanks
Last active June 25, 2019 06:32
Show Gist options
  • Save simeonwillbanks/5708448 to your computer and use it in GitHub Desktop.
Save simeonwillbanks/5708448 to your computer and use it in GitHub Desktop.
#AngularJS templates and #rails with eager loading -- prefill the AngularJS $templateCache. Inspired by @minhajuddin -- http://minhajuddin.com/2013/04/28/angularjs-templates-and-rails-with-eager-loading
# /code/railsapp/app/assets/javascripts/thing/app.js.coffee
#= require angular/templates
angular.module("thing", ["app.templates"]).value("appName", "thing")

AngularJS app JavaScript keyed by app name thing

/code/railsapp/app/assets/javascripts/thing/

AngularJS app templates keyed by app name thing

/code/railsapp/app/assets/templates/thing/

Shared AngularJS modules

/code/railsapp/lib/assets/javascripts/angular/

<%
# /code/railsapp/lib/assets/javascripts/angular/templates.js.coffee.erb
template_cache = []
# Prefill templateCache with latest templates
if Rails.env.production? || Rails.env.staging?
Dir.glob(Rails.root.join("app", "assets", "templates", "**", "*.haml")).each do |f|
pathname = Pathname(f)
template = {}
# /code/railsapp/app/assets/templates/thing -> assets/thing
template[:dirname] = pathname.dirname.sub(Rails.root.join("app", "assets", "templates").to_s, "assets")
# /code/railsapp/app/assets/templates/thing/page.html.haml -> page.html
template[:basename] = pathname.basename(".haml")
# ["/", "assets/thing", "page.html"] -> /assets/thing/page.html
template[:path] = File.join("", template[:dirname], template[:basename])
# Render HAML to HTML
template[:markup] = Haml::Engine.new(pathname.read).render
template_cache << template
end
end
%>
angular.module("app.templates", []).run(["$templateCache", "appName", ($templateCache, appName) ->
templates = [
<% template_cache.each do |template| %>
path: "<%= template[:path] %>"
markup: """
<%= template[:markup] %>
"""
,
<% end %>
]
appPath = "<%= File.join("", "assets", "") %>" + appName
# Only prefill the cache for the current app
$templateCache.put(template.path, template.markup) for template in templates when template.path.indexOf(appPath) == 0
])
@MrOrz
Copy link

MrOrz commented Nov 7, 2013

I changed the HAML rendering part with ERB renderer.

# Render ERB to HTML
template[:markup] = ERB.new(pathname.read, nil, nil, 'tmpl').result(binding)

And it worked for my ERB templates :)

@kimardenmiller
Copy link

Our app is just a single app, so the appName references were not needed.

Additionally, as credited elsewhere, you need depend_on(f) to keep the cache changing when your templates change:

<%
template_cache = []
# Pre-fill templateCache with latest templates for all environments
if Rails.env.production? || Rails.env.staging? || Rails.env.development?
  Dir.glob(Rails.root.join("app", "assets", "templates", "**", "*.haml")).each do |f|
    depend_on(f)
    pathname = Pathname(f)
    template = {}
    # /code/railsapp/app/assets/templates/thing -> assets/thing
    template[:dirname] = pathname.dirname.sub(Rails.root.join("app", "assets", "templates").to_s, "assets")
    # /code/railsapp/app/assets/templates/thing/page.html.haml -> page.html
    template[:basename] = pathname.basename(".haml")
    # ["/", "assets/thing", "page.html"] -> /assets/thing/page.html
    template[:path] = File.join("", template[:dirname], template[:basename])
    # Render HAML to HTML
    template[:markup] = Haml::Engine.new(pathname.read).render
    template_cache << template
  end
end
%>
angular.module('spokenvote.templates', []).run(['$templateCache', ($templateCache) ->
    templates = [
        <% template_cache.each do |template| %>
        path: "<%= template[:path] %>"
        markup: """
                <%= template[:markup] %>
                """
    ,
        <% end %>
    ]

    # Pre-fill the Angular cache
    $templateCache.put(template.path, template.markup) for template in templates
])

Finally, I'd love to see an example of this logic moved into a helper method :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment