Ajax with new controller action rails - javascript

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])

Related

ActionController::UnknownFormat with respond_to js for AJAX

I am searching for the internet about this topic, but I don't get how AJAX works with rails, I already check the documentation and I just simply don't understand it.
What I know is that AJAX is asynchronous and it just only takes to put this code in the view for make the request: "remote:true", the big deal that I don't get it is about this code:
respond_to :js
Apparently, it tells the controller that it would respond to Javascript and you have to make a file for whatever you wanna do with JS, my structure of my project is this one:
View
New.html.erb:
<p>Imagen de portada</p>
<%= simple_form_for #entries, remote: true do |f| %>
<% f.file_field 'input-image' %>
<% end %>
<div id="image-entry"></div>
View route:
views
|
-->admins
|
-->entries
|-->new.html.erb
|-->new.js.erb
Controller
entries_controller.rb
module Admins
class EntriesController < ApplicationController
before_action :authenticate_admin!
def index
render 'index'
end
def new
#entries=''
render 'new'
respond_to :js
end
end
end
Controller route:
controllers
|
-->admins
|
-->entries_controller.erb
JS
new.js.erb
console.log('funciona');
$('#input-image').click(function(){
$('body').css('background-color', 'red');
});
JS route:
views
|
-->admins
|
-->entries
|-->new.html.erb
|-->new.js.erb
Error
My error in this code is the following:
ActionController::UnknownFormat
So, I have questions about this error and what is the correct name of the file in JS for get the respond_to work correctly.
Answer by Irfan Fadilah on Facebook:
Your request is not processed by "new" method in EntriesController. The default form method is POST, so Rails will looking for "create" method in you EntriesController.
You can read RESTful routing in Rails Guide for more details.
In order to make your AJAX request to works. Add "create" method in EntriesController and create.js.erb (just write alert("Hello"); or something to test it) in views/entries.

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' %>");

Rails render JS partial printing code to page

I'm using AJAX in my Rails app to render a JS error message when needed. It was working initially, but now coming back to it some time later, it still shows the JS error message but for some reason it now also prints the entire JS file as HTML in the window. This is what's called in the controller:
respond_to do |format|
format.js { render :partial => 'error' }
end
My file named _error.js.erb contains some JS which isn't relevant as regardless of what it contains Rails prints it to the window still.
This is what the JS looks like outputted to the window: (I tried commenting out the JS to see if it made a difference)
You can try it with some modification :
respond_to do |format|
format.js
end
Inside the action and in the view action_name.js.erb write your js code ar if you want to put your erb then use escape_javascript.
Check the following link :
Why escape_javascript before rendering a partial?
I did it! In case there will be someone else wondering a few years later, there's the answer: you should put rendered value in a javascript_tag inside your html.erb. Like this:
javascript_tag render: 'error'
that will put what rendered between <script>...</script> tags and escape all unnecessary code.
Here's the documentation on it

rails redirect_to format html sends response in js

I made a before_filter in some of my controller to redirect keyword searches to the parent controller
It's very simple:
before_filter :redirect_search
def redirect_search
redirect_to controller: "buildings", action: "index", format: "html" if params[:q].present?
end
Please note that the keyword_search is sent in "js" format
Everything seems to work. When I look at the server, I can see that the buildings/index is run and that the page is rendered but nothing happens in the browser.
In the browser's console I see this
GET http://localhost:3000/buildings.html 200 OK
It has the html page in the response body
This means that buildings/index is run as html but then sent as js to the browser.
Why is that so? How can I fix it?
Try with
def redirect_search
respond_to do |format|
format.html {redirect_to buildings_path} if params[:q].present?
format.js {render :js => "window.location.href='"+buildings_path+"'"} if params[:q].present?
end
end
Thanks to Bachan's answer, I could solve my issue this way:
def redirect_search
render :js => "window.location.href='"+buildings_path+"'" if params[:q].present?
end
Thanks!
I think the problem is in the view which is doing the request
you are sending a JS request (ajax), so you should return a js.erb file and render new HTML using js

How to make an AJAX call to different domains in Ruby on Rails 3.0

I have an action email in my controller of application running on www.example.com and I am trying to send the form data of email to www.data.example.com/email where my another application receives the request and I am able to save the data in js format. But I want to send back the acknowledgement to www.example.com and replace the html using rjs template. Here are some code for you reference:
email.html.erb called on www.example.com
<div id="div_content">
<%= form_for(#user, :url => "http://data.example.com/mail", :remote => true) do |f| %>
<%= f.label :email %>
<%= f.text_field :email%>
<% end %>
</div>
email action of application on : data.example.com/email -
def email
#user = User.create(params[:user])
respond_to do |format|
if #user.save!
format.html { redirect_to(user_page_path(#user.vip_id), :notice => 'Thank you! You are now on our priority list.') }
format.js
else
format.html { render :text => "user can not be saved at this moment!"}
end
end
end
email.js.rjs called on www.data.example.com/email
page.replace_html :div_content, :partial => "show", :object => #user
I can see in my log that request comes all the way from one domain to sub domain and even action gets triggered but, I can not get the response back to the main domain. So, is there any way to send a callback to main domain. I just want to reflect changes there at the form which is inside div_content div and want to replace with content of _show.html.erb which I have on my sub domain.
Many Thanks,
Surya :)
This is happening because rails thinks you are trying to launch a cross site request forgery attack against yourself. By default rails has a security feature baked in that rejects form submission from outside sources (ie your other app)
Easiest (but not the most secure), way around it would be to add this to the top of the controller you are posting the data to:
protect_from_forgery :except => :email
RE COMMENTS
Ahh I see, I was not paying very close attention when I first read your post, sorry about that. I missed all the parts about rjs.
I am certainly no expert on rjs but it looks like you are doing most everything right. Only suspicious part to me is this line:
page.replace_html :div_content, :partial => "show", :object => #user
I think it should be:
page.insert_html(:bottom, "div_content", :partial => "show")
Also you might want to try and replace the rjs template with
page.alert("debug");
Just to make sure its really not coming back, because I would suspect it is...
Guys here is what I got to make it work -
Well I was trying to do cross domain communication using my both RoR app as I mentioned right up there in my question!
Finally I have found a way to achieve the same using "EasyXDM" (www.easyxdm.net) it solved the problem. It works great on most of the browsers including IE7 and Firefox older versions.
CORS is another solution if you want to get it done, but it fails to work on IE7...
whoa! now I can rely on the cross domain communication between my different apps without using an iFrame.

Categories

Resources