I'm working with a site using client-side templates through knockout.js.
The backend api, and login, is written in rails.
What I want to do is have each client-side html template in a separate file, and then have those templates lifted into the page using the templates. Similar to how javascript files are lifted in.
So I have a directory in my app/assets called templates
Each template in the directory should be added to the page in a script tag with the type="text/html"
I've gotten so far as to product the actual templates content now I just want to put it in the html.erb file in the head property.
However it always lands in the Body as normal text, not as HTML.
I've defined the following method in my controller:
def html_templates
output = ''
templates = Dir.glob 'app/assets/templates/*'
templates.each { |template|
file = File.open(template, "rb")
output += '<script type="text/html" id="'+(File.basename template, '.html')+'">'
output += file.read
output += '</script>'
}
return output
end
I try to add it to the .erb layout file like so:
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<%= html_templates %>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
Yet the output is always put in the body, with all my html escaped.
Also, if anyone has better solutions to have to solve this. Please, recommend.
Thanks :) so basically you should use raw method whenever you don't want output to be escaped
Related
I want to generate a PDF with our department logo in it. When I try to use the WickedPdf class in my controller (using the method described at https://github.com/mileszs/wicked_pdf):
def some_action
image_tag_string = image_tag('logo.jpg')
pdf = WickedPdf.new.pdf_from_string(image_tag_string)
save_path = Rails.root.join('testpdfs','logotest.pdf')
File.open(save_path, 'wb') do |file|
file << pdf
end
end
...the application saves the PDF to the target directory, but it has a blue-and-white '?' mark where the image should be.
If I do this instead:
image_tag_string = wicked_pdf_image_tag('logo.jpg')
pdf = WickedPdf.new.pdf_from_string(image_tag_string)
I get the following error:
NoMethodError:
undefined method `wicked_pdf_image_tag' for #<...
It would appear that my Rails app is also missing / not linking to a helper file belonging to the wicked-pdf gem.
Answers to similar questions on StackOverflow recommend writing a custom "image-tag" helper to locate the image or installing wkhtmltopdf. For me, image-tag shows the logo just fine when placed in a View (whatever.html.erb). "logo.jpg" is already located in both the asset pipeline and #{RailsRoot}/public/images. Finally, I am using wkhtmltopdf 0.9.9, wicked-pdf 0.11.0, and rails 4 on Ubuntu 14.04.
In a nutshell - what am I doing wrong that causes WickedPDF to fail to render the image?
First thing create a pdf template to render and use your wicked_pdf tags in that template..
for example-
app/views/layout/application.pdf.erb-
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
</head>
<body onload='number_pages'>
<div id="content">
<%= yield %>
</div>
</body>
</html>
app/views/pdf/pdf_view.pdf.erb-
<div>
<%= wicked_pdf_image_tag 'logo.jpg' %>
</div>
use this template instead
def save
pdf = WickedPdf.new.pdf_from_string(
render_to_string(
template: 'example/pdf_view.pdf.erb',
layout: 'layouts/application.pdf.erb'))
send_data(pdf,
filename: 'file_name.pdf',
type: 'application/pdf',
disposition: 'attachment')
end
This might help you..
Use the wicked_pdf_image_tag helper in your view and reference the image with asset_url if your image is in public/images or use asset_pack_url if the image is in public/packs/media/images
<%= wicked_pdf_image_tag asset_url('/images/footer_logo.png') %>
or
<%= wicked_pdf_image_tag asset_pack_url('media/images/footer_logo.png') %>
I converted image url that 'http' from 'https'. Than worked.
Heroku-18
Rails 4.2
wicked_pdf (1.1.0)
wkhtmltopdf-binary (0.12.4)
In my case, I am using carrierwave, the solution was taken from this post
<img src="<%= root_url + "/" +file.service_url %>">
This worked on rails 5.
I've been having trouble switching from a default layout.erb file to an equivalent layout.haml file in Middleman. I want to use HAML for my layouts since I'm trying to become familiar with it, so I decided to replace the default layout with a HAML version. Unfortunately, when I replace layout.erb with layout.haml, I get this error:
NoMethodError at /
undefined method `force_encoding' for nil:NilClass
Ruby /Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in ensure in binary, line 289
Web GET localhost/
Traceback (innermost first)
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in ensure in binary
string.force_encoding(original_encoding)...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in binary
string.force_encoding(original_encoding)...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in extract_magic_comment
binary script do...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in extract_encoding
extract_magic_comment(script) || script.encoding...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in precompiled
template_encoding = extract_encoding(template)...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/erb.rb: in precompiled
source, offset = super...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/erb.rb: in precompiled
source, offset = super...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in compile_template_method
source, offset = precompiled(locals)...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in compiled_method
compile_template_method(locals_keys)...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in evaluate
method = compiled_method(locals.keys)...
/Library/Ruby/Gems/2.0.0/gems/tilt-1.4.1/lib/tilt/template.rb: in render
evaluate scope, locals || {}, &block...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/core_extensions/rendering.rb: in render_individual_file
content = template.render(context, locs, &block)...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/core_extensions/rendering.rb: in render_template
content = render_individual_file(layout_path, locs, opts, context) { content }...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/sitemap/resource.rb: in block in render
app.render_template(source_file, locs, opts, blocks)...
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.1.4/lib/active_support/notifications.rb: in instrument
yield payload if block_given?...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/util.rb: in instrument
::ActiveSupport::Notifications.instrument(suffixed_name, payload, &block)...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/application.rb: in instrument
delegate :instrument, to: ::Middleman::Util...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/sitemap/resource.rb: in instrument
delegate :logger, :instrument, to: :app...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/sitemap/resource.rb: in render
instrument 'render.resource', path: relative_source, destination_path: destination_path do...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/core_extensions/request.rb: in process_request
output = resource.render do...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/core_extensions/request.rb: in block in call!
process_request(env, req, res)...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/core_extensions/request.rb: in catch
catch(:halt) do...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/core_extensions/request.rb: in call!
catch(:halt) do...
/Library/Ruby/Gems/2.0.0/gems/middleman-core-3.3.3/lib/middleman-core/core_extensions/request.rb: in call
dup.call!(env)...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/builder.rb: in call
to_app.call(env)...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/urlmap.rb: in block in call
return app.call(env)...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/urlmap.rb: in each
#mapping.each do |host, location, match, app|...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/urlmap.rb: in call
#mapping.each do |host, location, match, app|...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/showexceptions.rb: in call
#app.call(env)...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/head.rb: in call
status, headers, body = #app.call(env)...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/lint.rb: in _call
status, headers, #body = #app.call(env)...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/lint.rb: in call
dup._call(env)...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/builder.rb: in call
to_app.call(env)...
/Library/Ruby/Gems/2.0.0/gems/rack-1.5.2/lib/rack/handler/webrick.rb: in service
status, headers, body = #app.call(env)...
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/httpserver.rb: in service
si.service(req, res)...
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/httpserver.rb: in run
server.service(req, res)...
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/server.rb: in block in start_thread
block ? block.call(sock) : run(sock)
layout.erb looks like this:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<!-- Always force latest IE rendering engine or request Chrome Frame -->
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
<!-- Use title if it's in the page YAML frontmatter -->
<title><%= current_page.data.title || "The Middleman" %></title>
<%= stylesheet_link_tag "normalize" %>
<!-- <%= stylesheet_link_tag "normalize", "all" %> -->
<%= javascript_include_tag "all" %>
</head>
<body class="<%= page_classes %>">
<%= partial "header" %>
<%= yield %>
<%= partial "footer" %>
</body>
</html>
layout.haml doesn't have quite the same content as layout.erb, but that doesn't seem to matter since it breaks no matter what:
!!!
%html
%head
%title
= current_page.data.title || "The Middleman"
= stylesheet_link_tag "normalize", "all"
= javascript_include_tag "all"
%body
= partial "header"
= yield
= partial "footer"
At first I thought the error was only ocurring because the HAML itself was broken, but even a very simple HAML file that defines only doctype, html, head, title and body tags breaks. I then suspected that only ERb files were being taken as layout files - which I confirmed by renaming layout.haml to layout.erb, which didn't cause an error but just displayed raw HAML code instead. Even keeping layout.erb and making a sublayout article_layout.haml causes a similar error when navigating to a blog article, while making an article_layout.erb works fine.
So, I suspect that Middleman just won't accept anything except ERb for layout files. I can't find a single thing about this in the documentation, though, and I've even seen examples that all have layout.haml files that work perfectly fine. Is mine just different? Is there a flag I need to set with middleman init in order to use HAML files for layouts? What's going on?
As #r.pazyaquian mentioned in the sub-comments, if you change your layout file type, make sure to restart the server.
I am trying to get the name of the current view being loaded into layout.erb. I am trying to inject a js file and a css file into the layout head. I am building the name for those files based on the name of the erb view:
<link rel="stylesheet" href="/devcss/<%= viewName%>.css">
<script src="/devjs/<%= viewName %>.js" type="text/javascript"></script>
How can I do this from the layout template?
UPDATE:I am not interested in knowing how to inject the script in a specific place in layout, which I think content_for is used for. What I need to knok in the example above is how to determine the viewName variable
Insert the following into application.html.erb after inside head tag
<%= "#{yield(:scripts)}".html_safe if content_for?(:scripts) %>
and in the individual erb, insert similar to the following
<% content_for :scripts do %>
<link rel="stylesheet" href="/devcss/<%= viewName%>.css">
<script src="/devjs/<%= viewName %>.js" type="text/javascript"></script>
<% end %>
This will allow you to insert page specific codes into head and other tags not accessible to your individual erbs
How can I put meta tag to work only for one page. If I want to put it .aspx file, where is right place.
Thanks.
Since you haven't said yet, I'm assuming you're using the Razor engine (the "default" for new MVC3 projects). In that case, you just need to insert a new section into your layout view, and only render that section if you need to insert a meta tag.
For example, working from the stock New ASP.NET MVC 3 Project template, you would edit your Views\Shared\_Layout.cshtml file, and before the closing </head> tag, do something like this:
#this.RenderSection("MetaContent", false)
</head>
Then, in any of your views that you needed to, add this:
#section MetaContent
{
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
}
If you're still using the ASPX layout engine for some reason, you can accomplish the same thing using the <asp:ContentPlaceHolder> tags in your master page and <asp:Content> tags in your views.
EDIT:
Since you're using the ASP.NET Forms layout engine still, here's the same basic idea as above in aspx syntax:
In your master page, you add the tag:
<asp:ContentPlaceHolder ID="MetaContent" runat="server" />
</head>
And in your .aspx views, you add a new content section (you should already have at least two -- a title and a body):
<asp:Content ID="Meta" ContentPlaceHolderID="MetaContent" runat="server">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
</asp:Content>
I was going to suggest exactly what Michael said (+1). Another option would be to put a boolean in the ViewBag, something like:
ViewBag.ForceIE8Mode = true;
For pages that you want to force into IE8 Mode.
and then in your view, wrap the meta tag in a conditional. either
#if(ViewBag.ForceIE8Mode == true) {
<meta... />
}
or
<% if(ViewBag.ForceIE8Mode == true) { %>
<meta... />
<% } %>
I have a .html.erb file, with some javascript in it. I would like to do something like this:
var stuff = '<div><%= #ruby_var.title %></div>'
What is the best way to do this? I may be totally off... Thanks.
To safely do this you need to use to_json:
<%= javascript_tag do %>
var stuff = <%= #ruby_var.title.to_json %>;
<% end %>
This will ensure your code does not break if #ruby_var.title has a quote in it.
To include the divs I would do:
<%= javascript_tag do %>
var stuff = <%= "<div>#{#ruby_var.title}</div>".to_json %>;
<% end %>
Note that there are no quotes around <%= %>, to_json takes care of that for you.
<script>
var stuff = '<div><%=escape_javascript #ruby_var.title %></div>'
</script>
in your .html.erb file will work fine.
Ruby can't be run on the client, at least not with specialized browser plugins. Instead, look at using AJAX and RJS to query your Ruby web application from Javascript and insert any text it returns into your page.
Without more information, I don't think you're going to get any better answers. I might be totally off too, because I'm only guessing at what you really want to do.
You can use the javascript_tag function to include Javascript in a .html.erb file.
Example:
javascript_tag "alert('This is a test')"
in your foo.html.erb will return
<script type="text/javascript">
//<![CDATA[
alert('This is a test')
//]]>
</script>
to the browser.