Does will pagination work with forms which have method="POST"? - ruby-on-rails

I switched my advanced order form to POST from GET as the URI request became too large for browsers to handle. Everything works fine, with the exception of will pagaination. It keeps adding the page to the url itself http://localhost:3000/orders/advanced_search like http://localhost:3000/orders/advanced_search?page=2 which fails as this is a post call, and not a get call.
Any way that it can just update the params[:page] but not do anything to the link?
I used to just call <%= will_paginate #orders["order_items"] %> which worked great when it was a GET call where
#orders["order_items"] = #orders["order_items"].paginate(:page => params[:page],
:per_page => limit, :total_entries=>#orders["total"])
What I want is simple, add it to params, but do not add it to the link.

The other answer posted is wrong. will_paginate was NOT built to work with post requests.
Your choices to 'make' will_paginate work with post request include:
writing some javascript to:
preventDefault on click of the will_paginate-generated link
$(".pagination li a").click(function(e){
e.preventDefault(); ....
find the target page via the clicked link.
(below code is assuming all will_paginate links have a query string...which they do. But note that this particular line of code won't work if you are passing in more params in the controller via the params option for will_paginate..which you shouldn't be in the first place because we are trying to achieve a post request.)
var tp_id = $(this).attr("href").split('?page=')[1]
generate a hidden input with the correct name attribute depending on the clicked will_paginate link.
$('form').append("< input type='hidden' name='page' value='" + tp_id +"' >")
finally post to the controller action of the search form.
$('form').submit()
.done. I hope this puts you on the right path.

You can add a param to will_paginate
https://github.com/mislav/will_paginate/wiki/API-documentation
<%= will_paginate #orders['order_items'], :params => { :method => :post } %>
If it doesn't work, set te complete controller and action to params.

Related

acts_as_votable gem likes all the posts on page in rails

Lemme explain what I mean, the point is that I am using acts_as_votable gem in my rails app and it works fyn, problem is that I am using ajax and I am using it to like individual posts from my index page . I will explain with the code
This is my #confessions controller instance variable that has all the votes
#confessions = Confession.where(amitian_id: ids).order('created_at DESC')
Now this is my view that shows all the posts
-#confessions.each do |c|
# code
=link_to pluralize(c.get_upvotes.size,"Like"),like_confession_path(c) , method: :get,remote: true , class: 'like'
=link_to pluralize(c.get_downvotes.size,"Dislike"),dislike_confession_path(c) , method: :get,remote: true ,class: 'dislike'
end
Well, up until now I can use 'c' variable to refer to a single post.. but in my ajax script I have something like this
$('.like').html('<%= pluralize(#confessions.get_upvotes.size,"Like") %>');
$('.dislike').html('<%= pluralize(#confessions.get_downvotes.size,"Dislike") %>');
Now obviously, this will like all the post variable #confessions have.. how can i write a script to make it like the post user clicks on
I suppose I have to use this or self keyword but m not sure how.. help plz
Move the confessions block to a separate partial. Then wrap that partial in a div. Then in your ajax script you can just reload the partial.
View:
<div id=confessions>
<%= render 'confessions' %>
</div>
Ajax
$('#confessions').html("<%= escape_javascript(render 'confessions') %>")
Also, are you sure you want to be making GET requests to like/dislike? I think you should be making a POST request here.

Rails : Redirect to previous page with AJAX Response

I have this page where I have a form_remote_tag that returns an AJAX, paginated response :
<% form_remote_tag :url => searchs_path, :html => {:id => "search_form"} do %>
<!-- Blah -->
<% end %>
Results are printed in another div and point to totally different views. Now my main concern is not about browsing through the paginated results. My objective is that once I click on a result thus going to a different URL, I can just get back to the main search form filled with the previous AJAX response.
I tried using the HTML5 history API but it looks like it just helps browsing through the one-pager (which is not top-priority for me). I am thinking about page caching though it might be an overkill. Any thoughts on this ?
Finally managed to solve the problem by storing AJAX DOM Data via localStorage API.

Adding AJAX 'add to favorite' to this controller?

This is blowing my mind, and there is so much going on that I just need to ask here for help.
Right now, I have a listing of resources. Inside each resource, it allows someone to 'add it as a favorite' by clicking a link. I have it working with normal redirection, but as for integrating ajax so they can favorite without the page refreshing, I am completely lost...
Right now I have it as a "put" action it seems for CRUD 'update'
FavoritesController (update is the only action in this controller)
def update
#favorite = Favorite.find_or_initialize_by_resource_id_and_user_id(params[:id], current_user.id)
if #favorite.persisted?
#favorite.destroy
else
if #favorite.valid?
#favorite.save
end
end
redirect_to root_url
end
My view:
<%= link_to "", favorites_path(:id => resource.id), :class => "star#{star_post?(resource)}", :method => "put" %>
My routes:
resource :favorites, :only => [:update]
My JS:
$('.res-list .star').click(function(){
$.put('/favorites/?id=' + $(this).attr('data-id'));
return false;
});
There's a couple of ways to do this. You can use link_to_function through which you can pass a javascript method (you can even pass a custom one if you've defined it in the view or in application.js). In this method, you can set up your AJAX call to hit your update action.
View (using jQuery's put macro):
<%= link_to_function "AJAX Link", "$.put('/favorites/#{resource.id}');" %>
Another way to do this is to give your link an addition HTML selector. Again, you would need to write a bit of js to hit your update action. I tend to like this way because I like to use buttons and what not instead of <a href="#"> tags. (Though honestly I ended up just creating a button_to_function method that calls content_tag(:button) instead of content_tag(:a))
I would recommend starting off with this Railscast on basic JQuery and Ajax processing. It's a bit dated, but is pretty solid still and will give you the basics to get you started.
http://railscasts.com/episodes/136-jquery
It will give you an idea of how to attach the ajax call to the element on your page, handle request processing and craft a basic javascript view partial that will update the form for the user.
Good luck!

Rails controller not rendering correct view when form is force-submitted by Javascript

I'm using Rails with jQuery, and I'm working on a page for a simple site that prints each record to a table. The only editable field for each record is a checkbox. My goal is that every time a checkbox is changed, an ajax request updates that boolean attribute for the record (i.e., no submit button).
My view code:
<td>
<% form_remote_tag :url => admin_update_path, :html => { :id => "form#{lead.id}" } do %>
<%= hidden_field :lead, :id, :value => lead.id %>
<%= check_box :lead, :contacted, :id => "checkbox"+lead.id.to_s, :checked => lead.contacted, :onchange => "$('#form#{lead.id}').submit();" %>
<% end %>
</td>
In my routes.rb, admin_update_path is defined by
map.admin_update 'update', :controller => "admin", :action => "update", :method => :post
I also have an RJS template to render back an update. The contents of this file is currently just for testing (I just wanted to see if it worked, this will not be the ultimate functionality on a successful save)...
page << "$('#checkbox#{#lead.id}').hide();"
When clicked, the ajax request is successfully sent, with the correct params, and the action on the controller can retrieve the record and update it just fine. The problem is that it doesn't send back the JS; it changes the page in the browser and renders the generated Javascript as plain text rather than executing it in-place.
Rails does some behind-the-scenes stuff to figure out if the incoming request is an ajax call, and I can't figure out why it's interpreting the incoming request as a regular web request as opposed to an ajax request.
I may be missing something extremely simple here, but I've kind-of burned myself out looking so I thought I'd ask for another pair of eyes. Thanks in advance for any info!
In your controller you need to specify the proper response. Since you didn't post the controller I'll just try to fill in the blanks.
def update
# Update something
respond_to do |format|
format.js # this renders your rjs file
end
end
Specifying the format tells the rails app to interpret the javascript instead of just sending it back as text.
The other option instead of using rjs is to do an inline rjs block like this:
render :update do |page|
page.replace_html 'user_list', :partial => 'user', :collection => #users
page.visual_effect :highlight, 'user_list'
end
Only use the inline rjs if you will be doing minimal changes to the interface that can be put into one or two lines. Anything more should be in it's own rjs file.
This question is related to this one, but the answer varies slightly. I had to create a new way to submit the form, since the default jQuery submit() method does not submit as a 'script' and certainly does not fire the code that Rails generates in the onsubmit="..." handler via the form_remote_tag helper.
The solution was to create a new function as the linked answer suggests, but the contents are slightly different:
jQuery.fn.submitWithAjax = function() {
jQuery.ajax({data:jQuery.param(jQuery(this).serializeArray()) + '&authenticity_token=' + encodeURIComponent('<%= form_authenticity_token %>'), dataType:'script', type:'post', url:'/update'});
return false;
};
This is brittle right now-- notice that I insert rails' form_authenticity_token into the Javascript, but really the method (post) and the url (/update) should also be generated rather than hardcoded.
Things are working A-OK now.

Best way to get will_paginate working with Ajax

If you google "will_paginate" and "ajax", the top result is this blog post: But the original author of will_paginate says to not use this method (bad for SEO/spiders) ...
But I cant get the original authors method to work (his javascript kills all my links). An other gentleman suggests a similar method to mislav's (the original will_paginate author) concept. But I cant get that to work either.
so .... what is the best way to paginate using AJAX, and stay SEO friendly? (for RAILS >2.1)
Tomh's answer is correct. Just for shiggles, I prototyped a quick implementation. Here's a screencast that shows it using Ajax when Javascript is enabled (your users) and still having pretty URLs when Javascript is disabled (Google). And here are a few code snippets to get you rolling on it.
config/routes.rb:
map.connect 'items/:page', :controller => "items", :action => "index", :page => 1
app/controllers/items_controller.rb:
class ItemsController < ApplicationController
def index
#items = Item.paginate(:all, :page => params[:page])
respond_to do |format|
format.html
format.js do
render :update do |page|
page.replace_html :items, :partial => "items"
page << "ajaxifyPagination();"
end
end
end
end
end
app/views/items/index.html.erb:
<h1>Listing items</h1>
<div id="items">
<%= render :partial => "items" %>
</div>
app/views/items/_items.html.erb:
<%= will_paginate #items %>
<table>
<% for item in #items %>
<tr>
<td><%= item.id %></td>
</tr>
<% end %>
</table>
layout:
<%= javascript_include_tag :defaults %>
public/javascripts/application.js:
$(document).ready(function() {
ajaxifyPagination();
});
function ajaxifyPagination() {
$(".pagination a").click(function() {
$.ajax({
type: "GET",
url: $(this).attr("href"),
dataType: "script"
});
return false;
});
}
My example uses jQuery (with jRails), but it's straightforward to do with Prototype as well.
Seo friendly and unobtrusive javascript goes hand in hand. What you can do is the following.
Code the entire site as if only html is enabled (incl your pagination thing)
Use respond_to and serve only the list of items if the request comes in from js
Using onDomReady from whatever library you pick you attempt to catch all pagination links and add an onclick event which triggers an ajax call to that new view and returns the result. You put that result into the container containing the data you are paginating. The onclick then returns false.
To give your users a better user experience you can add some features like active links etc to the same javascript method.
Using this approach the pagination will work for JS and non-js as the non-js users (including Googlebot) will traverse your pagination as normal. Only in the event that the user has javascript enabled, the container with data will be updated with new results.
Unfortunately, I don't think you can use Ajax in the way you want and still stay SEO friendly as far as the paginated content. The problem is that the robots of Google and friends, as far as I know, won't go through your content using XHR requests so they simply won't see that content.
That said, if the paginated items each have their own static, SEO-friendly pages (or are otherwise statically available on your site), the content will still find its way into their engines. This is the way you'll probably want to go.
There is a railscasts on this topic which helped me out http://railscasts.com/episodes/174-pagination-with-ajax
I'm running rails 3.2, so I added the pagination.js there mentioned to app/assets/javascripts folder
pagination.js
$(function() {
$(".pagination a").live("click", function() {
$(".pagination").html("Loading...");
$.getScript(this.href);
return false;
});
});
And then created
home.js.erb
$('#div_tags_list').html('<%= escape_javascript(render partial: '/customersb2b/user_customer_numbers_list').html_safe %>')
$('#receipts_list').html('<%= escape_javascript(render partial: '/customersb2b/feed').html_safe %>')
Since I have two distinct listings on my homepage.
This is all I had to do to put will_paginate working with Ajax.
As for the SEO concerns, well, I don't know much about it, but the URL http://localhost:3000/customers?_=1366372168315&feed_page=1&tags_page=2 still works
There is a great way to do this easily if not worried about spiders. Took me 5 minutes. Check out:
https://github.com/ronalchn/ajax_pagination/wiki/Adding-AJAX-to-will_paginate
If you get an error about a missing 'history' file, install:
https://github.com/wweidendorf/jquery-historyjs
but also be aware of:
rails ajax_pagination couldn't find file 'history'

Resources