I am using the ERB engine to generate an offline HTML version of a page of my Rails website. The page shows great when shown by Rails, but I have trouble generating with ERB by myself (despite using the same ERB template).
First I was getting the error undefined method 't' and I solved it by replacing all <%=t(...)%> calls with <%=I18n.translate(...)%>.
Now I get undefined method 'raw'. Should I replace all <%=raw(...)%> calls with something else? If yes, what?
raw is defined as helper in actionpack/action_view library so that without rails you can't use it. But ERB templating shows its output without any escaping:
require 'erb'
#person_name = "<script>name</script>"
ERB.new("<%= #person_name %>").result # => "<script>name</script>"
And because of this for purpose of escaping there is ERB::Util#html_escape method
include ERB::Util
ERB.new("<%= h #person_name %>").result # => "<script>name</script>"
While #warhog 's answer will work, the include isn't necessary. It adds all the ERB::Util methods to the current class, which usually isn't desired and can cause unexpected side effects (if you had another h method for example). Instead just access the h method (or other helpers) using the ERB::Util class:
ERB.new("<%= ERB::Util.h #person_name %>").result
Related
I'm trying to get Markdown to play nicely with .erb. I'd like to use high_voltage to render markdown pages (or normal .html.erb files with markdown partials) that are parsed with Redcarpet and am struggling to get it to all work together.
At the moment I have an initializer called markdown_template_handler.rb that contains the following code:
class MarkdownTemplateHandler
def erb
#erb ||= ActionView::Template.registered_template_handler(:erb)
end
def call(template)
compiled_source = erb.call(template)
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
"#{markdown.render(compiled_source.source).inspect}.html_safe;"
end
end
ActionView::Template.register_template_handler(:md, MarkdownTemplateHandler.new)
However it is failing at line 7, compiled_source = erb.call(template) with the error code saying "wrong number of arguments (given 1, expected 2)"
I looked at the ERB Ruby documentation but from what I understood, the call method is a derivative of the new method, which only requires 1 argument, the text. However, when I tried to use it just in a quick rails console session, it also required two arguments.
When I remove the requirement to parse erb from the above code, everything works as expected, so I don't think it has anything to do with Redcarpet not working.
I am using Rails v6.0.0.rc1 & Ruby v2.5.3p105
Any help is appreciated.
Edit
Further research has led me to finding the Rails 6.0 ERB ActionView template handler. The call method of this handler does indeed require two arguments, the template and the source. That said, in Rails 5.2.3, the ERB Action View template handler call method only requires one argument, the template.
Could someone please point me in the direction of figuring out what source is in this context? There is no documentation for it that I can find.
In this case, source would be passed to the call by ActionView when the handler is called.
You would rewrite your call function like that:
def call(template, source)
compiled_source = erb.call(template, source)
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
"#{markdown.render(compiled_source).inspect}.html_safe;"
end
Before Rails 6, the source value was extracted from template.source, but it is now passed as a separate parameter.
This approach for rendering markdown with ERB in Rails 6 worked well for me. Thanks to Louis-Michel for pointing me in the right direction, including both parameters in the call.
require 'redcarpet'
class MarkdownTemplateHandler
def erb
#erb ||= ActionView::Template.registered_template_handler(:erb)
end
def call(template, source)
compiled_source = erb.call(template, source)
"Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(begin;#{compiled_source};end).html_safe"
end
end
ActionView::Template.register_template_handler(:md, MarkdownTemplateHandler.new)
I'm attempting test a helper in Rails 4 that calls h(some_content) but when I run my unit tests I receive: undefined method 'h' for PageHelperTest.
How can I call h inside my helper, but still be able to execute the code in test? The code works correctly when hit through the website.
The h method is defined on ERB::Util which isn't available in the helper test. I fixed the issue by changing the helper to call ERB::Util.h(some_content)
Well I just hit similar issue.
However changing the helper just for the tests to pass is a NO NO to me.
So I tried around and this solved it (HOWEVER in Rails 3.2.22):
include ERB::Util
alias_method :html_escape, :h
I guess it's not the cleanest way (the alias, and what if another helper needs some other thing). So I guess there would be some better way (include some group of modules or whatnot) - but this one works.
In my Rails web application, we are exporting a table of contents to a PDF file. For that we have used Prawn Gem. Earlier I had huge lines of code inside the below given block, but I reduced the lines by putting codes in to different methods:
pdf = Prawn::Document.generate("#{Rails.root}/#{file_name}") do
print_pdf_header(report, period)
map_table_header(parents)
map_table_content(hash, parents)
map_table_column_total(parents, hash)
array.each_with_index do |imagename, _index|
start_new_page
image "#{full_path}/#{imagename}.png",
vposition: :middle, position: :center, width: 500
end
end
print_pdf_header(report, period), map_table_header(parents),
map_table_content(hash, parents), map_table_column_total(parents, hash)
But, these methods I have used inside the Prawn Generate block gets 'undefined method' error.
NoMethodError (undefined method `print_pdf_header' for #<Prawn::Document:0x12f3bcec>)
So, please tell me how can I include a normal method inside Prawn::Document.generate block?
Thanks for any help offered :)
Prawn's generate method is just for very simple documents that don't require access to outside state or methods.
For what you're looking for, you should make use of Prawn::View instead. It will make it possible to call Prawn's document methods directly, but will also make the methods defined in your object accessible.
In my application, any time there is a form, I call two helper methods to inject some javascript into the head of the web page. One method injects code to focus on the first input of the form and the second method hooks up some call backs that I use with the client_side_validation gem.
I will be calling these two methods on any page that has a form_for in the view. Is there a way to automatically invoke these methods any time form_for is called as opposed to adding the calls to my template files?
Using Rails 3.1.
You should wrap form_for with your own method that calls your helpers. Fortunately Rails provides an easy way of doing this in the form of alias_method_chain.
module ActionView::Helpers::FormHelper
def form_for_with_my_helpers (*args)
my_helpers
form_for_without_my_helpers (*args)
end
alias_method_chain :form_for :my_helpers
end
You can now call form_for_without_my_helpers with the normal form_for arguments if you don't want a form to use your helpers.
This can go somewhere that's in the load path. Or you can require the file holding this code.
You shouldn't be using Rails helper methods for these. You should be using jQuery. Add this to your application.js file:
$(document).ready(function() {
$('form>input:first-child').focus();
}
That's an example, use a similar method for the callbacks you're talking about.
I'm using 'time_ago_in_words' function in a view, and I need to test the output in the FunctionalTest.
But the test can not see 'time_ago_in_words' helper function.
What should I do in order to use these helper methods from FunctionalTests?
Include the ActionView::Helpers::DateHelper module in your test_helper.rb or test.rb files. And that's it, from the test console:
>> time_ago_in_words(3.minutes.from_now)
NoMethodError: undefined method `time_ago_in_words' for #<Object:0x3b0724>
from (irb):4
from /Users/blinq/.rvm/rubies/ruby-1.9.1-p376/bin/irb:15:in `<main>'
>> include ActionView::Helpers::DateHelper
=> Object
>> time_ago_in_words(3.minutes.from_now)
=> "3 minutes"
I added on rails_helper.rb
config.include ActionView::Helpers::DateHelper
and work's, thank's #jpemberthy!
I had a similar issue recently where I was trying to access this function from an API so I wrapped it in a gem called timeywimey. Check it out: https://github.com/onetwopunch/timeywimey#usage
It allows you to access this helper from anywhere in a Rails project as well as Sinatra, and a native ruby project.
What exactly are you trying to test? You shouldn't need to verify the behavior of time_ago_in_words itself, because that's covered by Rails' own tests. If you're testing one of your own helpers that uses time_ago_in_words, the output can be checked in a helper test (which inherits from ActionView::TestCase).
Functional tests are intended for verifying the behavior of controllers (what template they render, whether they allow access, redirect, etc) which can include checking for the presence of certain HTML tags (by id). I usually try to avoid using them to check the content of the tags.