will_paginate icon indicating copy to clipboard operation
will_paginate copied to clipboard

Link to first page without a param

Open thebravoman opened this issue 9 years ago • 10 comments

I have an index /categories

The page /categories?page=2 generates a link to /categories?page=1

The problem is that /categories?page=1 and /categories is seen by search engines as two different urls but they are actually the same content. So the search engine sees identical content on two pages and I should use a canonical.

Is there a way to say to will_paginate to link the first page as /categories not as /categories?page=1

thebravoman avatar Dec 04 '15 16:12 thebravoman

In application_helper.rb,

  def paginate(collection, params= {})`
    will_paginate collection, params.merge(:renderer => LinkPaginationHelper::LinkRenderer)
  end

In link_pagination_helper.rb,

module LinkPaginationHelper
  class LinkRenderer < WillPaginate::ActionView::LinkRenderer
    def link(text, target, attributes = {})
      if text == 1
        return "<a rel=\"prev start\" href=\"/\">1</a>"
      end
      super
    end

    def previous_or_next_page(page, text, classname)
      if page == 1
        return "<a class=\"previous_page\" rel=\"prev\" href=\"/\">&#8592; Previous</a>"
      end
      super
    end
  end 
end 

and in index.html.haml

= paginate @posts

This should overwrite the 1 page link and also the previous link if you are on the 2nd page(i.e page=2).

(updated the name of the class and methods)

rishijain avatar Dec 09 '15 06:12 rishijain

But how do I get the url to be categories?

Because currently

"<a rel=\"prev start\" href=\"/\">1</a>"

redirects to / and i would like to redirect to categories/episodes/otherobject. The text,target, attributes do not give me the information for the controller where I am?

thebravoman avatar Dec 09 '15 06:12 thebravoman

You can hard code it in the link as href=\"/categories\" , right?

rishijain avatar Dec 09 '15 07:12 rishijain

I could, But I am using the will_paginate on all the controllers and this are episodes categories tags subtitles users

and other. So hard-coding it would not do.

How is will_paginate detecting if it is paginating episodes or categories or users?

On 9 December 2015 at 09:11, Rishi [email protected] wrote:

You can hard code it in the link as href="/categories" , right?

— Reply to this email directly or view it on GitHub https://github.com/mislav/will_paginate/issues/459#issuecomment-163136753 .

+359 878 93 30 94 Училище по роботика "Robopartans" www.robopartans.com

thebravoman avatar Dec 09 '15 07:12 thebravoman

ahhh ok. So you can do this:

in index.html

= paginate @posts, {"data-length" => 20, :controller_accessed => "posts"}

in link_pagination_helper.rb

module LinkPaginationHelper
  class LinkRenderer < WillPaginate::ActionView::LinkRenderer

    @object_type_accessed = nil

    def prepare(collection, options, template)
      @object_type_accessed = options[:controller_accessed]
      super    
    end

    def link(text, target, attributes = {})
      if text == 1
        return "<a rel=\"prev start\" href=\"/#{@object_type_accessed}\">1</a>"
      end
      super
    end

    #same logic for `previous_or_next_page` method
  end 
end 

Let me know if this works out.

rishijain avatar Dec 09 '15 08:12 rishijain

Tried it. Didn't work.

If I have an "episodes" controller with /episodes as url it works as expected. But if i have "categories" controller with /categories as url and I would like to show the episodes for the categories then the url is /categories/the_cat_name?page=X

And in this case the link for first page on /categories/the_cat_name?page=2 is /categories, while it should be /categories/the_cat_name.

thebravoman avatar Dec 09 '15 18:12 thebravoman

So basically you can assign any value to this object_type_accessed however you have your routes setup. Ex: for "episodes", in episodes index page(I am assuming you are displaying it on index page), you could set :controller_accessed => "episodes".

and in case of showing episodes for the categories, then you could pass in like this: :controller_accessed => "categories/the_cat_name".

I may be wrong here in understanding what you are doing.

rishijain avatar Dec 09 '15 18:12 rishijain

Yes. That's it. You understand it correctly

But then when I use pagination for episodes I must do paginate @episodes, {:controller_accessed => params[:controller]}

but when I am doing it for categories I must do paginate @episodes, {:controller_accessed => some_crazy_logic_to_check_if_this_is_a_category_and_what_is_the_path_to_it}

But because in both cases I am displaying episodes, but just for different parents I use the same partial. And now in the same partial I must have an if. And given that I have a playlists, that is another collection of episodes, where again the episodes are display it is there the same partial but with different special logic.

Wouldn`t it be easier if we build a config property for will_paginate? Something like set_number_first_page: true that does this?

thebravoman avatar Dec 09 '15 19:12 thebravoman

Yes, this is is not the cleanest and prettiest way to do it. It gets the job done :smile: And yes, an option to handle this use case would be helpful. But really this is the author's call.

I think this thread(https://www.ruby-forum.com/topic/182815) would also be of interest to you as it revolves around the same problem. Although solutions there are completely different.

rishijain avatar Dec 09 '15 19:12 rishijain

Thanks. Reading the threads now.

thebravoman avatar Dec 09 '15 19:12 thebravoman