I'm updating a site from rails 4.2 to 5.1
In the previous setup I have page caching on a generated stylesheet (per tenant), all working perfectly.
After upgrading to 5.1 this is no longer working
Using latest version of actionpack-page_caching
Controller for the Stylesheet that is cached looks like this:
class StylesheetsController < ApplicationController
caches_page :show, gzip: true
def show
#stylesheet = Stylesheet.find(params[:id])
respond_to do |format|
format.html
format.css { render text: #stylesheet.contents, content_type: "text/css" }
end
end
end
I'm getting the following error in the logs:
ActionView::MissingTemplate - Missing template stylesheets/show, application/show with {:locale=>[:en], :formats=>[:css], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby]}. Searched in:
There is no physical template for this as I'm rendering it directly from the stylesheet model. Have confirmed the model is returning data.
Caching is enabled in development.
In the layout page the reference to the dynamic stylesheet is:
<link href="<%= dynamic_stylesheet %>.css" rel="stylesheet" type="text/css" />
and the helper method (in application_helper) is:
def dynamic_stylesheet
stylesheet_path(current_account.stylesheet) unless current_account&.stylesheet&.id.nil?
end
I'm not sure what's getting skipped/missed here, any pointers?
Ok for anyone else who runs into this - the issue is a small change in Rails 5 with render text, in the controller example above it should now read:
format.css { render plain: #stylesheet.contents, content_type: "text/css" }
Found here What to use instead of `render :text` (and `render nothing: true`) in rails 5.1 and later?
Related
I have an uploader (internal use only) that will upload an HTML document to a binary column of a table in my client-facing website. The client facing site has an index that allows the user to view the page as a normal website (using send_data h_t.html_code, :type => "html", :disposition => "inline"). I also want to give the user the ability to download a PDF of the page. For that I'm using wicked_pdf.
The entire problem seems to stem from the fact that the data is stored in the database. As strange as it sounds, it is vital to business operations that I get formatting exact. The issue is I can't see any image, and the stylesheets/style tags don't have any effect.
What I've tried-
Gsub-
def show
html = HtmlTranscript.find(params[:id])
html_code = html.html_code.gsub('<img src="/images/bwTranscriptLogo.gif" alt="Logo">','<%= wicked_pdf_image_tag "bwTranscriptLogo.gif" %>')
html_code = html_code.gsub('<link rel="StyleSheet" href="" type="text/css">','<%= wicked_pdf_stylesheet_link_tag "transcripts.css" %>')
transcript = WickedPdf.new.pdf_from_string(html_code)
respond_to do |format|
format.html do
send_data transcript, :type => "pdf", :disposition => "attachment"
end
##### i never could get this part figured out, so if you have a fix for this...
# format.pdf do
# render :pdf => "transcript_for_#{#html.created_at}", :template => "html_transcripts/show.html.erb", :layout => false
# end
end
end
Using a template-
#Controller (above, modified)
html = HtmlTranscript.find(params[:id])
#html_code = html.html_code.gsub('<img src="/images/bwTranscriptLogo.gif" alt="Logo">','<%= wicked_pdf_image_tag "bwTranscriptLogo.gif" %>')
#html_code = #html_code.gsub('<link rel="StyleSheet" href="" type="text/css">','<%= wicked_pdf_stylesheet_link_tag "transcripts.css" %>')
transcript = WickedPdf.new.pdf_from_string(render_to_string(:template => "html_transcripts/show.html.erb", :layout => false))
#view
<!-- tried with stylesheet & image link tags, with wicked_pdf stylesheet & image link tags, with html style & img tags, etc -->
<%= raw(#html_code) %>
And both will generate a transcript- but neither will have style OR image.
Creating an initializer-
module WickedPdfHelper
def wicked_pdf_stylesheet_link_tag(*sources)
sources.collect { |source|
"<style type='text/css'>#{Rails.application.assets.find_asset("#{source}.css")}</style>"
}.join("\n").gsub(/url\(['"](.+)['"]\)(.+)/,%[url("#{wicked_pdf_image_location("\\1")}")\\2]).html_safe
end
def wicked_pdf_image_tag(img, options={})
image_tag wicked_pdf_image_location(img), options
end
def wicked_pdf_image_location(img)
"file://#{Rails.root.join('app', 'assets', 'images', img)}"
end
def wicked_pdf_javascript_src_tag(source)
"<script type='text/javascript'>#{Rails.application.assets.find_asset("#{source}.js").body}</script>"
end
def wicked_pdf_javascript_include_tag(*sources)
sources.collect{ |source| wicked_pdf_javascript_src_tag(source) }.join("\n").html_safe
end
end
did absolutely nothing, and I have no idea what to try next.
As a side note, the code to view the HTML version of the transcript is as follows:
def transcript_data
h_t = HtmlTranscript.find(params[:id])
send_data h_t.html_code, :type => "html", :disposition => "inline"
end
It requires no view, as the html data is stored in the database, but I get image, style, etc. Everything works with the HTML version- just not the PDF.
I'm on ruby 1.8.7 with rails 3.0.20.
Solved-
As it turns out, there was more than one issue at hand.
1- Installation of wkhtmltopdf for Ubuntu via $apt-get install does not quite do the trick for what I wanted...
see http://rubykitchen.in/blog/2013/03/17/pdf-generation-with-rails
(there may have also been an issue with having not previously run sudo apt-get install openssl build-essential xorg libssl-dev libxrender-dev, as when I did, it installed a number of components I did not previously have.)
2- The HTML files I had uploaded contained image & style code that was breaking the formatting. I fixed it with this...
def rm_by_line(which = 0, line1 = 0, line2 = 0)
h_t = HtmlTranscript.find(which)
line_by_line = h_t.html_code.split('
')
for i in line1..line2
line_by_line[i] = ''
end
line_by_line = line_by_line.join('
').strip
return line_by_line
end
Then, all I had to do was pass which lines I wanted to remove.
(I had to split the parens with a carriage return because '\n' didn't function properly when calling 'raw' on the returned string.)
3- wicked_pdf_stylesheet_link_tag and wicked_pdf_image_tag were undefined. I had to inline the style formatting I wanted into a layout I created (turns out wicked_pdf_stylesheet_link_tag used asset pipeline wich my ruby/rails did not implement, which also means I had to get rid of the javascript helpers) and created a helper for wicked_pdf_image_tag, making a switch in the layout for which image tag (image_tag or wicked_pdf_image_tag) to be used.
4- I needed both a .html.erb & a .pdf.erb for my templates, so I made both.
5- Got rid of WickedPdf.new.pdf_from_string in favor of linking to either html or pdf by using :format => 'html' or :format => 'pdf' in the link_to tag.
I'm having some issue figuring out how to handle success on my entries form using rails 3 ujs ajax.
If there are errors, I have a create.js.erb that will alert(j(#entry.errors.full_messages), and this works. But if there are no errors, the form doesn't redirect (because I'm rendering in a dialog) and I'd like the js to alert("success") and close the dialog. (using fancybox 2).
Can you give me some pointers working with rails 3 ujs and ajax?
An approach is to identify and handle the error at controller level instead of view.
def create
#entry = something
if #entry.save
#notice = "Success message!"
respond_to :js # render default create.js.erb
else
respond_to :js { render 'create_error.js.erb' }
end
end
// create.js.erb
$("#dialog").close();
alert("<%= #notice %>">;
// create_error.js.erb
alert(j(#entry.errors.full_messages);
How can I add a favicon in Active Admin. I am using rails 3.2 and active admin 0.4.3
Though this question is about an older version of ActiveAdmin, as of this commit ActiveAdmin supports favicons in the initializer. Around line 145 of active_admin.rb for me:
# == Setting a Favicon
#
# config.favicon = '/assets/favicon.ico'
HTH the next person who comes along. I almost did the top-voted answer...
Until they support favicon you can do the trick:
$(document).ready(function(){
$('head').append("<link href='favicon.ico' rel='shortcut icon'>");
});
You'll have to add it to your ActiveAdmin.rb initializer like so :
module ActiveAdmin
module Views
module Pages
class Base < Arbre::HTML::Document
def build_active_admin_head
within #head do
insert_tag Arbre::HTML::Title, [title, render_or_call_method_or_proc_on(self, active_admin_application.site_title)].join(" | ")
insert_tag Arbre::HTML::Link, rel: 'shortcut icon', href: '/favicon.gif'
# Change the href used in this line ^
active_admin_application.stylesheets.each do |style|
text_node(stylesheet_link_tag(style.path, style.options).html_safe)
end
active_admin_application.javascripts.each do |path|
script :src => javascript_path(path), :type => "text/javascript"
end
text_node csrf_meta_tag
end
end
I have searched around and have not been able to find a solution for this type of mechanic. I want to load all pages normally in Rails, but whenever I do an ajax request I just want to return the page without the layout. So anytime I make an ajax requst I can append a ?page=true or something along those lines and have Rails just return the page without the layout.
Is this possible? Is there a better way to do it that I am missing?
Thanks for any help!
Final Solution Working Code:
In the controller all you need to do is append a little logic to the format.html in the respond_to block.
In the show method for example
def show
# code beforehand
respond_to do |format|
format.html { render :layout => !request.xhr? }
# other formats
end
end
And that's it! Prevent layouts during AJAX requests!
Note: Thanks to the smathy's comment on his answer this was simplified further. I originally had format.html { render :layout => nil if request.xhr? } This solution works just as well, but smathy's modification keeps it even simpler.
You don't need to add that parameter, request.xhr? will return true in your controller when it's an Ajax request. Just use that to decide whether to render the layout or not.
So I realize that Rails mailers need help in generating urls. I want HTML email with images served externally (no attachments) so I've set both:
config.action_mailer.default_url_options = { :host => "localhost:3000" }
config.action_mailer.asset_host = "http://localhost:3000
and two things happen in my mailer template:
It hates the use of image_tag. Just barfs with an action view template error
url_for does nothing for unnamed routes. shouldn't it prepend the asset_host? for assets in public?