Rebuild Haml assets in development - ruby-on-rails

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.

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.

ruby code is showing as html in template

I have a rails app which uses angularjs. Here I'm trying to render a template from rails controller and pass a resource to the template. But the ruby code for displaying the variables are showing exactly as it is in the html.erb view.
def fail
#order = Order.find(1)
render 'payments/fail'
end
in view
<%= #order.as_json %>
My guess would be that the problem is in the name of your view file. I'd guess that you named it something like fail.html instead of fail.html.erb. Without the .erb suffix, Rails just interprets the file as html text and renders it without interpreting the ruby code.
However, changing the file name isn't quite the correct solution. Since you want to render json instead of HTML you don't need to create a view template, so you should just delete the template file altogether.
All Rails models have an .as_json method automatically, so you can simply modify your controller's fail method like so:
def fail
#order = Order.find(1)
render json: #order.as_json
end
Also if you want to do something fancy and modify the json that is returned, you can define your own as_json method inside the model.

rails, make render add a HTML comment of the filename being rendered for development

I'm working with an application whose is a bit complicated and was not designed by me. As it uses A LOT of partials, It would be really helpful if I could automatically add an html template each time a new erb/rhtml file is rendered.
So for exmaple if code have this:
<%= render(:partial => 'personal_details', :object => #auser) %>
the ouput html add something like:
<!-- Rendering: views/users/_personal_details.rhtml called from other_file.rhtml -->
How to acoomplish that?
First of all, are you already using xray-rails to visualize your partials? It is an incredibly useful tool.
If you need something more than that, take a look at the xray-rails source code for some pointers. Essentially what you'll need to do is monkey-patch ActionView::Template#render as shown here.
To summarize:
ActionView::Template.class_eval do
def render_with_prepend_comment(*args, &block)
# Defer to original implementation to do the actual render
source = render_without_prepend_comment(*args, &block)
# Then augment it as desired
"<!-- prepended comment -->\n" + source
end
alias_method_chain :render, :prepend_comment
end
There's a little more to it; see how xray-rails does its augmentation.
This gem claims to support the functionality you desire.
Rails >= 6.1 includes an option for ActionView called annotate_rendered_view_with_filenames which determines whether to annotate rendered view with template file names. This defaults to false.
In your case, you probably want to add the following to your development.rb configuration file:
# Annotate rendered view with file names.
config.action_view.annotate_rendered_view_with_filenames = true
This results in commented annotations similar to these in your rendered HTML:
<!-- BEGIN app/views/layouts/partials/_header.html.erb -->
<header></header>
<!-- END app/views/layouts/partials/_header.html.erb -->
Here is the description from the guides and here is the implemenation in Rails itself.

Is there a way to render a different template based on current user without using conditionals

I have two different layouts, one is completely custom and the other is bootstrap. For admins we want to render a bootstrap view and for non-admins we render it normally. For the most part this is pretty straight forward because admins and users don't share many views -- but there are some.
My original idea involved overriding render so that it would check if there's a bootstrap version of a file. So for example there would be _user.html.erb and _user.bootstrap.html.erb which would have bootstrap specific templating.
I'd like to not modify any controllers so ideally, something like render 'form' would behave smartly and check if there's an _form.bootstrap.html.erb, and if there isn't it would fallback to _form.html.erb
First attempt
My first attempt looked something like this
# I don't think this is the actual method signature of render
def render(options=nil, extra_options, &block)
# if it should render bootstrap and options is a string and there exists a bootstrap version
# set it up to render the bootstrap view
super(options, extra_options, &b)
end
Current attempt
I'm thinking about registering a template that basically checks if a file exists and then uses erb. I haven't made any progress towards this yet.
I figured it out. This is how I did it:
This is set in the application controller, with a before_filter :render_bootstrap
def render_bootstrap
return unless bootstrap?
new_action = "#{self.action_name}.bootstrap"
has_bs_view = template_exists?(new_action,params[:controller],false) || template_exists?(new_action,params[:controller], true)
if has_bs_view
self.action_name = new_action
end
end
I decided to extend this even further so that inside of a view like show.bootstrap.html.erb you can still use render "form" without doing render "form.bootstrap". This was done by overwriting the rails render helper.

How can I include an arbitrary file into a HAML template?

I want to have independent .markdown files that I then include in my haml templates. So I want to somehow include -- not render -- an external file into the template. I want the parent file to have :markdown in it, with the inclusion directly below that, and then the .markdown file to just be pure markdown.
Or: Is there a way to just use markdown as a rails template language (same way i can write templates or partials in erb or haml and rails just figures it out)?
This is similar to your solution, but using the :markdown filter. Haml does string interpolation on any filtered text, so you can read the markdown file like this.
:markdown
#{File.read(File.join(File.dirname(__FILE__), "foo.markdown"))}
You could put this into a helper, but you'd have to be careful with the file paths.
The simplest way I could think of is to create a custom template handler for Markdown. That you get to use Markdown code as partials (also getting support for locals for free).
module Markdown
class Template < ActionView::Template::Handler
include ActionView::Template::Handlers::Compilable
self.default_format = Mime::HTML
def compile(template)
'"' + Maruku.new(template.source).to_html + '".html_safe'
end
end
end
And then register it with markdown extension (in application.rb or custom initializer):
ActionView::Template.register_template_handler(:md, Markdown::Template)
And then user render like you would for any partial :)
# for file foo.md
= render 'foo'
Here's the best I can come up with (no haml filter involved at all):
=raw Maruku.new(File.read(File.dirname(__FILE__)+'/foo.markdown')).to_html
This is something I asked the HAML developers a while back. I suggested we needed an :include filter for HAML. Their response was we should load the file into a variable and then use the variable like we would any other.
Extending ActionView::Template::Handler is deprecated in at least Rails 3.1.0. Instead the following worked for me:
In lib/markdown_views.rb:
require "rdiscount"
class MarkdownViews
def call template
'md = ERB.new(<<\'EOF\'%s
EOF
).result( binding)
RDiscount.new( md).to_html.html_safe'% template.source
end
end
In config/application.rb:
require "markdown_views"
ActionView::Template.register_template_handler :markdown, MarkdownViews.new
In views/public/home.html.markdown:
# H1
+ Bullets.
+ screaming.
+ from out of nowhere
<%= "Embedded Ruby" %>

Resources