简体   繁体   中英

How do i paginate with array.collect in rails

I have a collection of stories that user likes, i want to paginate it.

For that i tried to do: (in user controller)

@stories = @user.likes.paginate(page: params[:page]).map { |e| e.story}

But i got an error: undefined method 'total_pages' for #<Array:0x007f9548c4cdd8>

on the partial:

<%= will_paginate @stories%>

(BTW, it works fine without paginating) What do i do wrong here?

More information:

The connections between models:

User model

class User < ActiveRecord::Base
  has_many :stories
  has_many :likes
end

Like Model:

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :story
end

Story model:

class Story < ActiveRecord::Base
  has_many :likes , dependent: :destroy
  has_many :users , through: :likes, source: :users
end

在调用分页之前添加以下代码。

require 'will_paginate/array'

The last part .map { |e| e.story} .map { |e| e.story} is the reason. Actually to use will_paginate @stories you need to have the @stories as will paginate object. But here you are getting just a simple array of stories where total_pages is not really unknown.

I didnt try the following but it will be somewhat like this

#FOLLOWING LINE MAY NOT WORK DIRECTLY!!
@stories = @user.likes(:include => :story).paginate(page: params[:page]) 

the point is @stories should have the output of paginate function. then will_paginate will work with the list.

EDIT: How about this.

@stories = (@user.likes.map { |e| e.story}).paginate(page: params[:page]) 

Actually i cant test it right now so just trying to figure it out based on my assumptions.

When you call map { |e| e.story} map { |e| e.story} you're throwing away the will paginate collection (which contains info such as which page are you on, total number of pages etc) and replacing it with a straight array.

Something like this should work:

likes = @user.likes.paginate(page: params[:page])
@stories = WillPaginate::Collection.create(likes.current_page, likes.per_page, likes.total_entries) do |pager|
  pager.replace likes.collect {|l| l.story}
end

This creates a new will paginate collection with the same metadata, but new contents.

I heard some ways how to do that

But the best one is to add to the User model:

class User < ActiveRecord::Base
  has_many :stories
  has_many :likes
  has_many :liked_stories, through: :likes , source: :story
end

And in the controller

@stories = @user.liked_stories.paginate(page: params[:page]) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM