Rails 4 render Gritter messages in js view - javascript

Using Rails 4.2.4, ruby 2.2.2, gritter gem 1.2.0. My controller respond with js:
#posts_controller.rb
if #post.update post_params
gflash :success => "Link updated"
end
in accordion with official doc this is my js view:
#update.js.erb
<%= gflash :js => true %>
The problem is none is rendered, Rails server works fine and no problems are show in console. I have inspected the produced js and I have see this:
jQuery(function(){jQuery.gritter.add({image:'/assets/success-0b8a2dedd729f28e513472812f5483ae2817ae482c0b744c3ce56c9dd2b2bc1d.png',title:'
Success',text:'Link updated'});});
It seems the browser doesn't render the jQuery function. (I have jquery allready installed in my app)
Ideas?

Solution:
Short: <%= (gflash :js => true).html_safe %>
Long: Inspecting server response with Fiddler Web Debugger I have notice the response is like this:
jQuery(function(){jQuery.gritter.add({image:'/assets/success-0b8a2dedd729f28e513472812f5483ae2817ae482c0b744c3ce56c9dd2b2bc1d.png',title:'Success',text:'Link updated'});});
If I execute the code above in chrome console I have an error:
VM8474:2 Uncaught SyntaxError: Unexpected token
So using the html_safe method works for me: <%= (gflash :js => true).html_safe %>

Related

Rendering a partial and escaping the html/javascript for a bookmarklet

I am trying to build a bookmarklet that makes a request to an action in localhost and displays a div with the html taken from the js response from localhost. I can make the request just fine, but when the js returns I have "undefined" in console. I tried debugging it using binding.pry and I saw that the content is not evaluating properly. This is how I tried evalauting it:
content = "<%= escape_javascript(render(:partial => 'events/bookmarklet').html_safe) %>";
In the binding.pry console I get the following response:
content = eval("<%= escape_javascript render(:partial => 'events/bookmarklet') %>");
SyntaxError: (eval):1: syntax error, unexpected '<'
<%= escape_javascript render(:partial => 'events/bookmarklet') %>
^
(eval):1: syntax error, unexpected ')', expecting end-of-input
<%= escape_javascript render(:partial => 'events/bookmarklet') %>
^
from (pry):12:in `eval'
I don't know why you try to eval something if I understand what you want to do correctly.
Use json and render_to_string if you want to pass html by javascript. So for your example:
# controller
def action_name
content =
render_to_string(
partial: 'events/bookmarklet',
formats: [:html], # always render html format, even if request wants json
layout: false # render only partial, without any layout
)
render json: { html: content }
end
You can access the content in javascript by data.html then.

Passing variable to Javascript doesn't work in Rails 4.2

I have just created a simple Rails 4.2 application to upload file to S3. I'm trying to follow this article https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails#submitting-and-rendering-the-images and it looks like in javascript <%= #variable %> gets parsed as string.
I tried this.
This is what I have in /users/new
# GET /users/new
def new
#s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: 201, acl: :public_read)
#user = User.new
end
And this is what I tried in application.js
window.vaz = <%= #s3_direct_post.url %>;
but when I do console.log(window.vaz); I get "<%= #s3_direct_post.url %>" instead of the real value.
I tried gon as well but gon has a lot of issues with Rails 4.2
I verified that #s3_direct_post.url returns something in the console.
Add .erb extension to application.js file (application.js.erb). <%= => is erb syntax and you need to process it as erb file first so that <%= #s3_direct_post.url %> is evaluated as ruby code.
http://guides.rubyonrails.org/asset_pipeline.html#preprocessing

j(render(#partial)) returns error: ActionController::UnknownFormat

I'm trying to render a partial with ajax, but for some reason it returns this error:
ActionController::UnknownFormat in ThingsController#upvoterandom
ActionController::UnknownFormat
I'm very confused because I accomplished something with an essentially identical format before, and I never had any problems with it. Does anyone see anything wrong with my code? I can render a string with the ajax; it's only when I try to render a partial that I get the error. By the way, I achieved this error by deleting the format.html line and then visiting the upvoterandom_thing path directly in my browser.
views/things/show.html.erb
<div id= "randomajax" >
<div id="randajax">
<%= link_to #rand.name, thing_path(#rand) %>
<%= link_to image_tag("UpArrowGray.jpg", class: "rand_up_vote"), remote: true, %>
<script type="text/javascript">
function reload_script() {
$(".rand_up_vote").click(function () {
$.get( "<%= upvoterandom_thing_path(:id => #rand.id) %>", function( data ) {
});
});
}
reload_script();
</script>
</div>
</div>
controllers/things_controller.rb I put asterisks around the line highlighted with the error.
def upvoterandom
#thing = Thing.find(params[:id])
#...
***respond_to do |format|***
format.html { redirect_to root_path }
format.js
end
end
views/things/upvoterandom.js.erb: .html("test") returns "test", so the problem has to be in the rendering.
$('#randomajax').html("<%= j(render(#randajax)) %>");
views/things/_randajax.html.erb
TEST
THIS IS THE OTHER NEAR-IDENTICAL AJAX STRUCTURE THAT WORKS:
views/things/show.html.erb
<%= form_for([#thing, #comment], remote: true) do |f| %>
<%= f.text_area :text %>
<%= f.submit "Post", id: "postacomment" %>
<% end %>
controllers/comments_controller.rb
def create
#thing = Thing.find(params[:thing_id])
#comment = #thing.comments.create(comment_params)
respond_to do |format|
format.html { redirect_to root_path }
format.js
end
end
views/comments/create.js.erb
$('#comments_h2').prepend("<%= j(render(#comment)) %>");
views/comments/_comment.html.erb
TEST
I'll apologize up front for the long answer. I've tried reproducing your issue in multiple ways, but I think you might be looking in the wrong direction. I've included the entire story so you can see if it all matches up, and if it doesn't it hopefully leads to insights which will help you resolve the issue.
ActionController::UnknownFormat happens before view rendering
If Rails presents you with the ActionController::UnknownFormat error, it means that your controller does not respond to the format that is being requested. The error is raised by the respond_to method, at the exact line you highlighted.
Had an error been raised during view rendering, then it would have been bubbled up through either the line with format.html or format.js. So this error is certainly not caused in the view rendering part.
Reproducing the ActionController::UnknownFormat error
The only way I can get the exact error message you posted, is if I request the AJAX response page directly in the browser. Then you see the Rails error page, which will also show you which format the request was done with. You're probably requesting the page with a format other than html or js, in which case the ActionController::UnknownFormat error is triggered, since your controller only responds to the html or js format.
I think the actual issue is hiding somewhere else.
Reproducing from views/things/show.html.erb
I have tried to reproduce the error from the views/things/show.html.erb page as well. When doing this with your original code, I get a syntax error on the following line:
<%= link_to image_tag("UpArrowGray.jpg", class: "rand_up_vote"), remote: true, %>
This happens due to the comma after remote: true. Because of this, I assume you haven't been constantly testing with the remote link. When testing it without the remote: true, the reload_script function triggers a jQuery AJAX request. You're doing this with the following line:
$.get( "<%= upvoterandom_thing_path(:id => #rand.id) %>", function( data ) {
});
This actually triggers an XHR request with the format */*. It basically tells Rails that any format will do. Here's what happens:
The ThingsController responds with the first format you've defined in the respond_to block, which is the HTML format. This triggers a redirect to your root path.
jQuery follows the redirect, again using the */* format.
The controller at your root path responds with the first defined format, or HTML by default if no respond_to block is present.
jQuery then loads that response.
There's no way that the ActionController::UnknownFormat could have been raised from ThingsController when reproducing it like this.
What I think
This is mostly guessing work, so please correct me if I'm wrong:
You clicked the upvote remote link and nothing visibly happened.
You added a JavaScript to explictly fetch the page through AJAX, but still nothing visibly happened.
You visited the things/1/upvoterandom.js (or alike) page directly with your browser. In this case an ActionController::InvalidCrossOriginRequest would have been raised.
You visited the things/1/upvoterandom.json (I used JSON, but it could be any format other than HTML or JS) page directly with your browser, and you got the ActionController::UnknownFormat error.
If this is how it happened, you need to go back to step 1, and start reproducing the issue in another direction:
Go to the things/1 (or another Thing ID) page.
Open up the Developer Tools/Web Inspector of your browser.
Go to the view which shows the network communication (in Chrome this is the tab called Network).
Now click the link, and see what communication happens between your browser and your Rails application. If a lot happens, you often can filter for XHR only, which only show AJAX requests.
If you see a 500 status popping up there, you need to check the Rails server output for an error with stacktrace.
I can only guess what the actual cause of the issue is, but I think it might actually be some error when rendering the view, As you said, the only case where it doesn't work is if you render the partial. I hope this information helps you to resolve the issue.
In views/things/upvoterandom.js.erb you're trying to render #randajax like so:
$('#randomajax').html("<%= j(render(#randajax)) %>");
But I don't see #randajax being assigned anywhere, which means that it's nil.
Trying to render nil is the cause of this issue. But do confirm this by doing the following the first:
$('#randomajax').html("<%= j(render(nil)) %>");
If it returns the same error, then we've found the culprit.
Either assign #randajax something prior to rendering it or simply use:
$('#randomajax').html("<%= j(render(path_to_partial)) %>");
Well I haven't figured out why the syntax I was trying wasn't working, but this syntax does work:
$('#randomajax').html("<%= render 'randajax' %>");

How can I render via CoffeeScript in Ruby on Rails 4

I was trying to solve this problem for a while with no result.
I've wanted to pass variables and load a render into a div using CoffeeScript in rails 4.
(I'm using SpreeCommerce platform).
view:
<%= link_to taxonomy.name,root_path+'t/'+tid, {class: "uno", remote: true} %>
controller:
respond_to do |format|
format.html
format.js # menu.js.coffee.erb
end
menu.js.erb.coffee:
$('div#productos').html("<%= escape_javascript(render :partial => /shared/products) %>")
I'd like to load the page '_products.erb.html' and the partial processes the variables that I give it. As soon as I know, view and controller are ok, the problem is in menu.js.erb.coffee
Any help will be apreciated!
ADDITIONAL:
I've modified the extension to .js.coffee.erb. When I try to run the app, it shows me:
"undefined method `render' for #<#:0xa70317c>"
I tryied using <%= raw escape_javascript( render :partial =>... almost always "render" method give me problems.
NEW INFO:
I added gem 'coffee-script' to the Gemfile (then 'bundle install').
Now, when I click the link_to, it shows me into the HTML <%= escape_javascript(render :partial => /shared/products) %> as a text instead of loading the "partial"... any suggestion please?
I wrote a post about this after struggling through the same problem.
You need to:
Name it menu.js.coffee. Suffixing .erb causes it not to be evaluated as CoffeeScript.
Use raw to escape it.
I used these two on my website. Here's how it looks:
<%= raw render 'path/to/menu.js.coffee' %>
It still processes ERB within your CoffeeScript.
I would recommend changing it from menu.js.erb.coffee to menu.js.coffee.erb.
Rails will process the file extensions from right to left. Meaning right now, your file is treated first as coffeescript, then as ruby, and finally as javascript. It looks like you want to make the ruby substitutions first, then parse the coffeescript into javascript, so that would be menu.js.coffee.erb
First of all, you should change file name from menu.js.erb.coffee to menu.js.coffee.erb and you need configuration file as follow, which is a contribution by cervinka on coffee-rails issue #36
config/initializers/coffee_erb_handler.rb
ActionView::Template.register_template_handler 'coffee.erb', Coffee::Rails::TemplateHandler # without this there will be template not found error
class ActionView::PathResolver < ActionView::Resolver
EXTRACT_METHODS = %w{extract_handler_and_format_and_variant extract_handler_and_format} # name for rails 4.1 resp. 4.0
method_name = EXTRACT_METHODS.detect{|m| method_defined?(m) || private_method_defined?(m)}
raise 'unknown extract method name' if method_name.nil?
old_method_name = "old_#{method_name}"
alias_method old_method_name, method_name
define_method(method_name) do |path, default_formats|
self.send(old_method_name, path.gsub(/\.js\.coffee\.erb$/, '.js.coffee'), default_formats)
end
end

Monitoring a server-side process on Rails application using AJAX XMLHttpRequest

I'm using the following in the web page but can't get a response from the server while it's processing
<script type="text/javascript">
<!--
function updateProgress() {
//alert('Hello');
new Ajax.Request('/fmfiles/progress_monitor', {
parameters: 'authenticity_token=' + encodeURIComponent(AUTH_TOKEN),
onSuccess: function(response) {
alert(response.responseText);
fillProgress('progressBar',response.responseText);
}
});
}
//-->
</script>
<% form_for( :fmfile, :url => '/fmfiles', :html => { :method => :post, :name => 'Form_Import', :enctype => 'multipart/form-data' } ) do |f| %>
...
<%= f.file_field :document, :accept => 'text/xml', :name => 'fmfile_document' %>
<%= submit_tag 'Import', :onClick => "setInterval('updateProgress()', 2000);" %>
The 'create' method in fmfiles_controller.rb then happily processes the file and gets the right results (as per the submit button on the form). If I uncomment the '//alert('Hello')' line I get a dialog saying Hello every 2 seconds ... as expected.
However, the server never logs any call to 'progress_monitor' method in 'files' not even a failed attempt.
If I click the link
Run
it makes a call to the server, gets a response and displays the dialog, so I assume the routes and syntax and naming is all OK.
I really don't know why this isn't working. Is it because 2 methods in the same controller are being called via URLs?
I'm using Rails 2.1.0 in a development environment on OS X 10.5.5 and using Safari 3.1.2
(N.B. This follows on from another question, but I think it's sufficiently different to merit its own question.)
If you are not seeing messages in your log file for the call to 'progress_monitor' then it is possible that the request is never being sent.
Try this:
Try using the full URL instead of the relative URL for the Ajax.Request. I have had problems with relative URLs on some browsers with the Ajax.Request.
Enable Firebug or the IE Developer Toolbar. You should be able to see if the call to progress_monitor works or not. If there is a java script error then you will see the error clearly using these tools.

Categories

Resources