Hi Ylan,

So, I think you are correct about code smells, but not in the same way I'm
thinking. A couple of things stand out to me as worrisome for long-term
maintenance and architecture. Here are some suggestions:

1) Make your index.js.erb views ONLY contain JSON.  The Rails community and
examples, for some reason, love to put logic in your javascript views to
update the page it's being rendered into. I think that is BAD!  If you GET
/users?format=js, it should return to you the JSON form of the user objects,
and should know nothing about what your client-side app wants to do with
that information. Your /users?format=html page should be responsible for
AJAX GET-ting the JS formatted version of /users and updating the HTML
element you want in a "on success" callback (in whatever lib you are using,
like JQuery). That logic should NOT be in the JS view you are rendering. If
you want to use that same /users?format=js call in a REST-ful client that
doesn't have a web browser component, how are you gonna parse that info? It
doesn't make much sense. That way of doing it limits the potential benefits
of the different view formats.

2) Wrap your pagination AJAX calls in a main, common javascript file that
gets included in each index view (or in your main layout), and in your
index.html.erb views write the specific code to implement it:

=============================
# public/javascripts/app/pagination_helper.js
var PaginationHelper = function (new_url, div) {             # Notice the
namespace of "PaginationHelper"? DON'T create global JS functions!
  var url = new_url;
  var div_to_update = div;

  var get_page = function (page) {
    $.get(url, {success: function (result) {
$('#'+div_to_update).html(result); } })     # <== Highly paraphrased here.
Assumes jQuery.
  };

  return {
    initialize_pagination: initialize_pagination,
    get_page: get_page
  };
}

# app/views/users/index.html.erb
<div id="users">
  <%= render @users %>
</div>

<script>
  document.ready(function () { pagination_helper = new
PaginationHelper('/users', 'users') });
</script>

==================

You can then program (ie: update the partials) the pagination links to call
"pagination_helper.get_page(<page_num_of_link_clicked_on>)", which is
already initialized to point to the URL you want when the /users page is
loaded, and will update your div with the results returned.

Now, I realize that code probably doesn't work, but that's how I've designed
other pagination pages before. This way, you can reuse PaginationHelper
everywhere, and each index page will just initialize it with the correct URL
the pagination links need. This offloads the burden of WHERE to render
things onto the HTML index page, not the JS page!

You can also make that "document.ready" code a partial that takes local vars
for the url and div_to_update, and then put that one partial call in all
your index views with the appropriate mods to those values.

Also, this is a sweet jQuery extension library that takes little effort to
implement, and basically works this same way:

http://www.datatables.net/

Hope that helps!

I'm curious to see others' takes on this, in case I'm full of shit.

- Adam

On Mon, May 9, 2011 at 1:28 PM, Ylan <[email protected]> wrote:

>
> Hey everyone, I need some help refactoring:
>
> I am using kaminari for pagination on a rails 3 project and I have
> successfully followed the example in the documentation.
>
> https://github.com/amatsuda/kaminari
> https://github.com/amatsuda/kaminari_example/tree/ajax
>
> As suggested in the example, my controller responds to js with
> index.js.erb. Here is the example code:
>
> #users/index.js.erb
> $('#users').html('<%= escape_javascript render(@users) %>');
> $('#paginator').html('<%= escape_javascript(paginate(@users, :remote =>
> true).to_s) %>');
>
> As you can see, there is some javascript that calls the html function in
> the browser to replace the results with the output of rendering the _users
> partial.
>
> So, everything is working at this point. My problem with this approach is
> that now I want to paginate another resource, let's say posts. Now, I have:
>
> #posts/index.js.erb
> $('#posts').html('<%= escape_javascript render(@posts) %>');
> $('#paginator').html('<%= escape_javascript(paginate(@posts, :remote =>
> true).to_s) %>');
>
> Which starts smelling immediately, because I just copy,pasted and replaced
> "users", with "posts" 3 times. Now, of course, later on it's likely that
> instead of just using html to replace, I will end up using some other jquery
> effect to paint it, in which case I will have to go back to each
> index.js.erb in my application, and start the copy/past find/replace.
>
> Any ideas on how to refactor this and create the appropriate javascript
> dynamically?
>
> Thanks,
>
> --
> Ylan.
>
> --
> SD Ruby mailing list
> [email protected]
> http://groups.google.com/group/sdruby

-- 
SD Ruby mailing list
[email protected]
http://groups.google.com/group/sdruby

Reply via email to