How can I include an arbitrary file into a HAML template? - ruby-on-rails

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" %>

Related

Stripping HTML markup from a translation string

I have some translations that I use in my views. These translations sometimes return very basic HTML markup in them -
t("some.translation")
#=> "This is a translation with some markup<br />"
(Side note: I'm using the fantastic it gem to easily embed markup, and specifically links, in my translations)
What if I wanted to strip the HTML tags in certain cases, like when I'm working with the translation string in my RSpec tests. Is there an HTML strp functionality that will compile and remove that markup?
t("some.translation").some_html_strip_method
#=> "This is a translation with some markup"
Thanks!
You may want to try strip_tags from ActionView::Helpers::SanitizeHelper
strip_tags("Strip <i>these</i> tags!")
# => Strip these tags!
strip_tags("<b>Bold</b> no more! <a href='more.html'>See more here</a>...")
# => Bold no more! See more here...
strip_tags("<div id='top-bar'>Welcome to my website!</div>")
# => Welcome to my website!
Depending on where you use it.
strip_tags method not functioning in controllers, models, or libs
It comes up with an error about white_list_sanitizer undefined in the class you’re using it in.
To get around this, use:
ActionController::Base.helpers.strip_tags('string')
To shorten this, add something like this in an initializer:
class String
def strip_tags
ActionController::Base.helpers.strip_tags(self)
end
end
Then call it with:
'string'.strip_tags
But if you only need to use it in VIEW, simply:
<%= strip_tags(t("some.translation")) %>

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.

Ruby on Rails - using helpers in html.erb

I'm probably missing some things.
Say for example I have a helper function in app/helpers/foo_controller.rb and the code is as follows:
def sample_helper(count)
#implementaton...
end
and I want to use this helper in a webpage generated by rails and the code is as follows:
<%= sample_helper(user.id) %>
and if I try to run the webpage it will throw me an error saying that the method is not defined.
Thanks in advance!
You don't quite have the naming conventions right.
Name your helper file app/helpers/foo_helper.rb and in it you should have this:
module FooHelper
def sample_helper(count)
"#{count} items" # or whatever
end
end
And now, from any view rendered by FooController you should be able to use the sample_helper method.
Also, you should know that if you use the rails generators this structure is setup for you. All you need to do is add methods to the files that get generated. That way you don't need to guess the naming conventions.
For example, this command will make a controller file, controller test files, a helper file, and and an index view file, all ready for you to customize.
rails g controller foo index
Is your helper should be in a file called app/helpers/foo_helper.rb that contains a a module of the same name as the helper (camelized) Like:
module FooHelper
def sample_helper(cont)
# implementation
end
end
That's the way Rail auto loads helpers.

Rails escapes HTML in my plain text mails

I am using the rails 3.2.5 ActionMailer to send plain text mails. Given I have a mail view like this:
message_from_user.text.erb:
Hi <%= #recipient.name %>,
You got the following message from <%= #sender.name %>:
<%= #message %>
When #message is "quotes & ampersands", then the plain text mail contains "quotes & ampersands". So it seems like rails just treats this as a HTML view and escapes any html in order to prevent cross site scripting. However this is a plain text mail. The extension is .text.erb and ActionMailer detectes this and sets the MIME to text/plain. So I never want to escape any html in it.
I have quite a few mail templates in my application, they are all plain text. I would consider patching all of them to include <%=raw #message%> or <%= #message.html_safe %> bad style - not very DRY.
I tried varios work-arounds that included money patching Erubis. None of them seem to work. I am looking for some patch or config option or anything to disable escaping html for all .text.erb files.
Any help is greatly appreciated!
After some hours of debugging through the Erubis code, I found the following fix. You can just put it into config/initializers/fix_my_mails.rb. I've tested this with rails 3.2.7. It may work with other versions.
module ActionView
class Template
module Handlers
class ERB
def call(template)
if template.source.encoding_aware?
# First, convert to BINARY, so in case the encoding is
# wrong, we can still find an encoding tag
# (<%# encoding %>) inside the String using a regular
# expression
template_source = template.source.dup.force_encoding("BINARY")
erb = template_source.gsub(ENCODING_TAG, '')
encoding = $2
erb.force_encoding valid_encoding(template.source.dup, encoding)
# Always make sure we return a String in the default_internal
erb.encode!
else
erb = template.source.dup
end
self.class.erb_implementation.new(
erb,
:trim => (self.class.erb_trim_mode == "-"),
:escape => template.identifier =~ /\.text/ # only escape HTML templates
).src
end
end
end
end
end
It just disables HTML entities in every erb file containing .text in the file name.
Try
<%= #message.html_safe %>
You'd found this answer if you had used the search function. If that doesn't suit your needs, maybe check
https://rails.lighthouseapp.com/projects/8994/tickets/4858-actionmailer-is-html-escaping-ampersand-in-urls-in-plain-text-messages
If you haven't seen that yet, some options are discussed there

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