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

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.

Related

Rails 4 render Gritter messages in js view

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 %>

Ajax with new controller action rails

I have created a new micropost controller action called more to receive ajax request.
def more
micropost=Micropost.find_by(params[:id])
#answers=micropost.answers
respond_to do |format|
format.html {redirect_to micropost}
format.js
end
end
and I have created jquery file- more.js.erb
$(".microposts").html("<%= escape_javascript(render('users/unfollow')) %>"); `
to replace the content with a partial
my route file is like
resources :microposts, only: [:edit,:create,:destroy,:update,:show,:more] do
member do
get :more
end
end
and i call the javascript file in the view with
<%= link_to "load more",more_micropost_path(micropost),remote: true %>
Its working with normal html request but not ajax.Nothing happens when I click on the link. I saw similar questions asked by some but the fixes are not working for me. Can someone help me with this. Thanks in advance..
The error in firebug console is
`500 internal server error.
NoMethodError in MicropostsController#more.
Undefined method id for nil:NilClass'
The firebug error console shows this jquery line on the right hand side. I am not sure if its an error.
lixhr.send( ( options.hasContent && options.data ) || null );
judging by the error you posted in the comments, this line may be a problem:
micropost = Micropost.find_by(params[:id])
find_by requires a hash, so either use find
micropost = Micropost.find(params[:id])
or
micropost = Micropost.find_by(id: params[:id])

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

Weird JSON Javascript problem in Rails

I'm trying to get my JSON from my controller to my view. In my controller I am doing:
#nodes = Node.all
#json = #nodes.as_json(:only => [:ID, :Lat, :Lon])
In my view I have tried:
1) var stuff = <%= #json %>
2) var stuff = <%= #json.to_json %>
3) var stuff = <%= #json.to_json.to_json %>
and all of those give me an error. I usually get an "Unexpected Syntax Error &" or "Unexpected Syntax Error {"
I have also tried using jquery and using respond_to within the controller, but that doesn't seem to work either.
My thoughts are that getting json to the view shouldn't be a big issue and shouldn't require jQuery, and currently, my page source looks like:
var stuff = [{"node":{"ID":1301499692582,"Lat":42.3605063113369,"Lon":-71.0870862191138}},{"node":{"ID":1301499691515,"Lat":42.3605147089149,"Lon":-71.0870533282532}},{"node":{"ID":1301431075499,"Lat":42.3605456103,"Lon":-71.0875239075536}} etc
I dont understand the &quot symbols (maybe thats where the syntax error is coming from) but when I do render :json => #nodes.to_json, the page renders a normal json that is valid:
[{"node":{"ID":1301499692582,"Lat":42.3605063113369,"Lon":-71.0870862191138}},{"node":{"ID":1301499691515,"Lat":42.3605147089149,"Lon":-71.0870533282532}},{"node":{"ID":1301431075499,"Lat":42.3605456103,"Lon":-71.0875239075536}}
Note: I've also tried doing var stuff = '<%= #json.to_json %> but when I do var json = JSON.parse(stuff), it gives me an illegal token error.
Can someone please help me with this? Thanks so much!
This is Rails html-encoding your string as is default in Rails 3.
You need to mark your JSON as html_safe:
var stuff = <%= #json.to_s.html_safe %>
Note that .to_s is needed because as_json gives Hash instead of string. You could do this instead:
# in controller
#json = #nodes.to_json(:only => [:ID, :Lat, :Lon])
#and in view
var stuff = <%= #json.html_safe %>
I think you need to put quotes around it, then you can ask jquery to parse the string into JSON.

Categories

Resources