Too may redirects rails respond_to - ruby-on-rails

I have a controller action method that gets all records of establishments from the DB, I then want to share this response with a external entity which is a RhoMobile application, i used respond_to to format the response to JSON.
def index
#establishments = Establishment.index(params).includes(:assessor)
#json_establishments = Establishment.all
respond_to do |format|
format.html { redirect_to(establishments_url) }
format.json { render json: #json_establishments.as_json }
end
end
When i navigate to this action i get an error
net::ERR_TOO_MANY_REDIRECTS
in chrome developer tools on the console tab.
When i remove the { redirect_to(establishments_url) } next to the format.html it's working with a status of 406 (Not Acceptable) but if i would use the search in the action view that i created and click the browsers back button, i get something like:
ActionController::UnknownFormat in EstablishmentsController#index
ActionController::UnknownFormat
<div class="source hidden" id="frame-source-0">
<div class="info">
Extracted source (around line <strong>#219</strong>):
</div>
instead and when i refresh the page i get the expected view.

No wonder that it is stuck in redirect loop.
Reason:
establishments_url points to EstablishmentsController#index, and your default format must have been html. So, after setting the variables, it redirects to establishments_url, which again tries to load EstablishmentsController#index.
Solution:
Instead of redirecting to the URL, you need to consider rendering a view (as you did in JSON format).
format.html { render 'establishments/index' }

Related

Displaying an error message without reloading the page in Rails

I have a page that lets one create records - if the validations aren't satisfied, it redirects to the same page and shows an error message. Here's that snip from the controller:
def create
#signature = Signature.new(signature_params)
if #signature.save
redirect_to "/thanks"
else
redirect_to :back, :notice => error_messages(#signature)
end
end
The trouble is, this is resulting in a full page refresh - so the error message isn't visible because the input form is placed under the fold of the page. I can place it at the top of the page, of course, but is there a way to show the message without reloading the page? Thanks.
OK, so here's what I've settled on:
1) I'm handling validation on the client side with HTML5 "required" attributes - they were created for this explicit purpose and no other gems or plugins are needed. They are supported in all major browsers. Details in this article.
2) I've moved the error messages to the top of the page to handle the case in which a user either is on an old or mobile browser or has JavaScript disabled. Error messages must work with a complete request-response cycle (even if this means re-loading the page) before they work with anything else - this is the unobtrusive JavaScript approach.
3) For the AJAX version, I'm going to be using remote: => true on the form element as explained in the Rails guides. I might be making this open source once I'm done with the callback part of it, and will post a link here.
Obviously, handling errors with flash is the most uniform & DRY way to show the user what's going on, but if you're willing to think outside the box, you'll be able to use Ajax to accomplish a similar job by just handling the errors yourself:
Code Example
#app/controllers/signatures_controller.rb
def create
#signature = Signature.new(signature_params)
if #signature.save
#success = "true"
end
respond_to do |format|
format.js { #errors = error_messages(#signature) }
format.html {
if #success.defined?
redirect_to "/thanks"
else
redirect_to :back, :notice => error_messages(#signature)
end
}
end
end
#app/views/signatures/create.js.erb
<% unless #success.defined? %>
alert(<%=j #errors.inspect() %>)
<% end %>
#app/assets/javascripts/signatures.js
$(document).on("submit", "#signature_form", function() {
$.ajax({
url: "/signatures"
type: "POST"
data: $(this).parent().serialize(); //serialize the form (not the button)
error: function() {
alert("Sorry, there was an error!");
}
});
});
You'd actually be better using JSON for this. If you like the idea, I can refactor it to include JSON for you!

Error in handling reponse from remote true Rails

I am using Rails remote true for ajax calls, but I have error in handling the response form controller.
What I am doing is I have placed a form in partial which I render in the view for the first time, and I have also given it a id in html options for form_for. I have also applied some jQuery on that form like on save and cancel button and one script for date picker on one of its field.
As I handle the response from server using format.js for rendering js file, in which I have placed the code as follows
if #vairable.save
format.js { render 'some-file' }
else
format.js { render 'something'}
end
If the variable saved successfully I close the form properly, but if validations occur I render the form again by writing JavaScript code in js.erb file. I have problem in handing this response. The errors are displaying properly but when the form renders again with errors, the jQuery events applied to its fields and button, do not work. The jQuery events don't take place.
This problem only occurs when the model validations occurs and the validation rails are displayed with the new render form.
You should wrap your response in a respond_to block like this:
respond_to do |format|
if #variable.save
format.js { render 'some-file' }
else
format.js { render 'something'}
end
end
Edit: Your jQuery tags should be changed to $(document).on(...). Eg.
#change this:
$("#your-target-id").click(function(){
alert("This doesn't work after your have submitted via ajax")
});
#to this:
$(document).on("click", "#your-target-id", function() {
alert("This should work after ajax submission, and when errors are displayed");
});

Returning: A full page, JSON, and a partial HTML snippet from Ruby on Rails Controller

I know this question has been asked in part a few other times on SO but I was curious about doing it a different way. In my Ruby on Rails app I have an action called list on my UsersController.rb controller. I want this list to respond to 3 different things
The page itself. Rending the whole page of users I specify
A JSON list of users for the page I specify
A partial view of just the rows for the page I'm specifying formatted as HTML.
Imagine a full page (header, footer, everything) with a table that has page 1 of users. When I click page 2 I want to kick off an ajax request back to the same controller action to give me just the html rows for page 2. I also want to persist my JSON API still allowing my controller to return JSON lists when asked. I imagine it looking someting like this.
class UsersController < ApplicationController
def list
respond_to do |format|
format.html # RETURNS MY VIEW
format.json # RETURNS MY JSON LIST
format.partial_html # RETURNS MY PARTIAL HTML
end
end
end
Is there anyway to accomplish this in RoR? Or am I doomed into having to create another action in my controller just to return technically the same data?
Could I make this happen by specifying my own MIME type? Should I snake in the partial as an XML return type?
Use format.js on the third line.
Put the partial html on a partial, call it app/views/users/_html_rows.html.erb.
render that partial both on the full html and on the js version.
You will have app/views/users/list.html.erb with the full html content, which will be something like this:
<html>
<body>
.....
<table id="my_table"><%= render 'users/html_rows', users: #users %></table>
</body>
</html>
You will have app/views/users/_html_rows.html.erb with:
<tbody>
<% users.each do |user| %>
<tr>
<td>user.name</td>
</tr>
</tbody>
Then you will have app/views/users/list.js.erb with:
$("#my_table tbody").html("<%= render 'users/html_rows', users: #users %>");
This probably will solve your problem.
You can add an additional mime type entry to work with respond_to. In config/initializers/mime_types.rb, add:
# htmlp means "html partial"
Mime::Type.register "text/html", :htmlp
In your controller you can now do:
def list
respond_to do |format|
format.html
format.json
format.htmlp { render layout: nil }
end
end
And create a template called list.htmlp.erb with your partial content in it.

How to pull a record with AJAX

On my site I have a simple model called Feed.
I want to make a link/button that will pull the Feed record with id=5 (for example) using AJAX.
The record that has been pulled should be displayed in a partial.
How can I do that ?
Thanks,
Oded
If you use jQuery, you could do sth like this:
In your controller you must respond to ajax request using the respond_to :js. Then you could either render directyl javascript which will be executed on your site, or the way I suggest you, to render json and parse it on the client side.
class YourController < ApplicationController
def index
#model = YourModel.all
respond_to do |format|
format.html
format.json {
render :json => #model.to_json
}
end
end
On the client side, just bind a click handler and then fetch the data using the path to your controller:
$("#your_link_id").click(function() {
$.getJSON('/path_to_your_controller', function(data) {
console.log(data);
});
}
The code is not tested, but it should work in that way.
Note: the console.log works with firefox but not with safari, try using firebug for console output.
Kind of long for a SO answer, but this should get you going:
http://www.tutorialspoint.com/ruby-on-rails-2.1/rails-and-ajax.htm
That's where I got started with AJAX on RAILS

Calling Rails update Method via Inline Edit

I was putting together a quick inline editing feature in my first Rails app and just as I was getting it working it occurred to me that I may be violating RESTful principles. The edit updated an image name. To do so, it submits, via PUT to Image#update and passes the new modified name as image[name].
The database gets updated properly, but I need that value back so that my markup can reflect the name change. To do that, I was calling /images/:id.json, but that got me wondering whether a PUT request can "validly" (in that RESTful sort of way) return a value like this.
Thoughts?
Update: For whatever it's worth, I'm using jQuery and the jEditable plugin to do the inline editing. Here's my jEditable code:
$(document).ready( function() {
$('h2').editable(
'/images/' + $('#image-id').val() + '.json',
{
method: 'PUT',
name: 'image[name]',
submitdata: { authenticity_token: $('#auth-token').val() },
submit: 'Save',
cancel: 'Cancel'
}
);
})
And my Image#update method as it exists right now:
def update
#image = Image.find( params[:id] )
if #image.update_attributes( params[:image] )
flash[:notice] = "Successfully updated image."
respond_to do |format|
format.html { redirect_to #image }
format.json { render :json => #image.to_json }
end
else
render :action => 'edit'
end
end
If your concern is just that your update method with JSON provide a response body and not just a 200 OK (Rails's head :ok) then I don't think you need to be worried. The default response is 200 OK so the only difference between what you're doing and what Rails does by default (in its scaffolds) is that you're also including a response body. As far as I can tell proper REST etiquette only requires that you return a 200 OK and doesn't care about the response body, which is in line with what you're doing.
Beyond that all your code looks excellent.

Resources