rendering a partial Rails3.x + coffeescript - ruby-on-rails-3

I have the following requirement. I have a 'school' drop down and as the last options I have add new school, so if the user selects that option I want to load the new_school form as a partial via ajax.
I'm on
gem 'rails', '3.2.9'
gem 'coffee-rails', '~> 3.2.1'
Jquery via gem 'jquery-rails'
Earlier with rails < 3 and prototype I used to do it with
Ajax.Updater (aka Rails link_to_remote :update => 'some_div')
and with rails > 3 + JQuery I'm familiar with *.js.erb, and having something like
$("#school_form").html("<%= escape_javascript(render(:partial => "form"))%>");
But I'm new to coffeescript and I have no idea on how to do this with coffeescript, can someone help me :), (because I believe you shouldn't have to do a server request for this)
So far I have done following to catch the select_tag change event
$ ->
$('#school_name_select').change ->
unless $(this).val()
$('school_name').html([I want to have the _new_school_form partial here])

Use a hidden div.
In general, you don't want to bother trying to mix JS and HTML. The escaping can be complicated, error-prone, and flat out dangerous due to the possibility of cross-site scripting attacks.
Simply render your form partial in a div that's not displayed by default. In ERB:
<div id="school_name_form" style="display: none;">
<%= render 'form' %>
</div>
In your CoffeeScript:
$ ->
$('#school_name_select').change ->
if $(this).val()
$('#school_name_form').slideUp()
else
$('#school_name_form').slideDown()
I recommend using a small, tasteful transition like slide or fade. It gives your app a more polished feel.
No AJAX is required. This pattern is so common that I have an application-wide style defined as follows.
.not-displayed {
display: none;
}
Then using HAML (if you're into that), the HTML template becomes simply:
#school_name_form.not-displayed
= render 'form'

You can try to render the form partial inside hidden div (not too correct from semantic point of view), or put the form html as data attribute of any relevant element, something like
f.select school_name, ... , data: {form: escape_javascript(render(:partial => "form"))}
And the Coffeescript
$ ->
$('#school_name_select').change ->
unless $(this).val()
$('school_name').html($('#school_name_select').data('form'))

Related

Wicked PDF, generating PDF from database table- images and style issues

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.

How to namespace coffeescript in a Rails project

In my Rails project, in which I am using Coffeescript, I want to be able to do something like this in a view:
f.text_area :content, :size => "77x4", :oninput => 'Helpers.expandTextarea(300)'
This would call a coffeescript function that would expand the textarea when required. My problem is that I can't seem to properly namespace the coffeescript to get this to work. I tried to do it like this
# site.js.coffee
Helpers =
expandTextarea: ->
alert "function found!"
This doesn't work. Trying to call Helpers in the browser console will throw an undefined error. My question is this:
What code would I use in site.js.coffee to achieve the namespacing I want?
You could manually put Helpers into the global namespace:
window.Helpers =
expandTextarea: ->
alert "function found!"
Then you should be able to say Helpers.expandTextarea(300) anywhere you want. Assuming, of course, that site.js.coffee is included on every page.
CoffeeScript files are wrapped in functions by default:
(function() { /* compiled CoffeeScript goes here */ })();
to avoid polluting the global namespace. You can supply options to the CoffeeScript compiler to not wrap like this but you're better off explicitly putting global things into window.

Override html in active_admin gem

I wanna override html code when working with active_admin gem in Rails; because the nav-bar and many elements in these gem's views are different with my views (other pages). I hope that has a way to change html code without changing css manually! Thanks
It is not very easy , activeadmin use DSL for building html (called "Arbre")
You have to monkey patch every page class, also , it may prevent customizing of css too.
For example to move sidebar to left, create initializer with next patch.
class ActiveAdmin::Views::Pages::Base < Arbre::HTML::Document
def build_page_content
build_flash_messages
div :id => "active_admin_content", :class => (skip_sidebar? ? "without_sidebar" : "with_sidebar") do
build_sidebar unless skip_sidebar?
build_main_content_wrapper
end
end
end
default method was
def build_page_content
build_flash_messages
div :id => "active_admin_content", :class => (skip_sidebar? ? "without_sidebar" : "with_sidebar") do
build_main_content_wrapper
build_sidebar unless skip_sidebar?
end
end
The full list of classes used for rendering can be found here , so some of them you need to patch.
https://github.com/gregbell/active_admin/tree/master/lib/active_admin/views
Be ready for a big piece of work.
UPD. Gem for changing activeadmin sidebar position
https://github.com/Fivell/active_admin_sidebar

In Rails 3, how can you make a div a button (a clickable div that links to a new page)

I know that there are options to do this manually, such as here : How do you make the entire DIV clickable to go to another page?
However, in Rails 3 we make links like this:
<%= link_to "name", url %>
And I am wondering -- is there a proper Rails way to make a whole div a button. I realize I could make a button. However, let's say I want to fill it with content like text and a picture - then how would I make that whole div clickable in a rails way?
For example:
<%= #story.title %>
<%= #story.blurb %>
In this example, I would want to make #story clickable, with the rails generated content that I specified.. Any ideas?
For those interested, the answer is:
<div class="class_name">
<%= link_to content_tag(:span, "Text for the LInk"), route %>
</div>
And then, in the CSS set .class_name to position:relative; and:
.class_name span {
width:100%;
height:100%;
position:absolute;
z-index:2;
top:0px;
left:0px;
}
The link will now assume the size of its parent container, and thus give the impression the whole container is a link.
I think that button_to is what you need :
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to
I might use jquery if you really wanted to do this
$(document).ready(function() {
$('#somediv').click(function(event){
document.location = 'http://someplace.com';
});
});
You can't make a "clickable" raw div like that in a rails way... the concept doesn't make any sense. That's just not how it works
(added missing close parens for click)
not tested

Rails 3: how to render text file in-line?

All.
A Rails n00b here...
I'm writing an application that reports the status of a transaction.
Some of the content in the rendered HTML comes from instance variables
initialized in the controller, while other content comes from text files
(e.g., log files) that I want to render in the HTML using <pre> tags.
What is the "Rails Way" to do this?
Thank you for your time...
<pre>
<%= render :file => '/tmp/test.log' %>
</pre>
Here you go: http://edgeguides.rubyonrails.org/layouts_and_rendering.html
In some cases (when the file is not small and loading it is connected with a delay), I prefer to load the page content and then to use jQuery ajax request to load the file content.
For example, let's say I have a model with file path attribute. In the view layout I am doing something like this:
<pre data-source=" <%= (#file.path) %>"></pre>
Then in the corresponding js file I am loading the context like this:
$(document).ready ->
$.ajax(
url: $("pre").data("source")
context: document.body
).done (response) ->
$("pre").html response
return
return
Of course you can check the jQuery ajax documentation for more options. For example, you can render the pre tag with loading like this:
<pre data-source=" <%= (#file.path) %>"><div class="loading"></pre>
or use other jQuery animations as well.