Programing

Ruby on Rails는 배열을 페이지 매김합니다.

crosscheck 2020. 10. 28. 07:46
반응형

Ruby on Rails는 배열을 페이지 매김합니다.


누군가가 객체 배열에서 will_paginate 를 사용하는 방법을 설명 할 수 있는지 궁금 합니다.

예를 들어 내 사이트에는 사용자가 의견을 평가할 수있는 의견 섹션이 있습니다. 의견을 평가 한 사용자를 모으기 위해 작성한 방법은 다음과 같습니다.

def agree_list
  list = OpinionRating.find_all_by_opinion_id(params[:id])
  @agree_list = []
  list.each do |r|
    user = Profile.find(r.profile_id)
    @agree_list << user
  end
end

감사합니다


will_paginate 3.0은 ActiveRecord::RelationRails 3 의 새로운 기능 활용하도록 설계되었으므로 paginate기본적으로 관계에 대해서만 정의 합니다. 여전히 어레이와 함께 작동 할 수 있지만 해당 부품이 필요하도록 레일에 지시해야합니다.

config/initializers(I used will_paginate_array_fix.rb) 의 파일에 다음을 추가하십시오.

require 'will_paginate/array'

그런 다음 배열에서 사용할 수 있습니다.

my_array.paginate(:page => x, :per_page => y)

Array#from페이지 매김을 시뮬레이션 하는 사용할 수 있지만 여기서 진짜 문제는 전혀 사용하지 않아야한다는 것 Array입니다.

이것이 ActiveRecord 연관 이 만들어지는 것입니다. 이 가이드를주의 깊게 읽어야합니다. Rails 애플리케이션을 개발하는 경우 알아야 할 유용한 정보가 많이 있습니다.

동일한 작업을 수행하는 더 나은 방법을 보여 드리겠습니다.

class Profile < ActiveRecord::Base
  has_many :opinion_ratings
  has_many :opinions, :through => :opinion_ratings
end

class Opinion < ActiveRecord::Base
  has_many :opinion_ratings
end

class OpinionRating < ActiveRecord::Base
  belongs_to :opinion
  belongs_to :profile
end

데이터베이스 스키마가 적절한 명명 규칙을 따르는 것이 중요합니다. 그렇지 않으면이 모든 것이 손상됩니다. 수동으로 수행하는 대신 데이터베이스 마이그레이션을 사용 하여 테이블을 생성하고 있는지 확인하십시오 .

이러한 연결은 모델에 도우미를 만들어 훨씬 쉽게 검색 할 수 있도록합니다. 대신 OpinionRatings의 목록이 반복 수동으로 사용자를 수집, 당신은 레일의 사용으로 당신을 위해이 작업을 수행 할 수 있습니다 named_scope또는 scope당신은 레일 2.3 또는 3.0을 사용하고 있는지 여부에 따라 달라집니다. 지정하지 않았으므로 두 가지 예를 모두 제시하겠습니다. OpinionRating 클래스에 다음을 추가하십시오.

2.3

named_scope :for, lambda {|id| 
  {
    :joins => :opinion,
    :conditions => {
      :opinion => { :id => id }
    }
  }
}

named_scope :agreed, :conditions => { :agree => true }
named_scope :with_profiles, :includes => :profile

3.0

scope :agreed, where(:agree => true)

def self.for(id)
  joins(:opinion).where(:opinion => { :id => id })
end

각각의 경우에 당신이 호출 할 수 for(id)OpinionRatings모델과 그것을 ID를 전달합니다 :

2.3

@ratings = OpinionRating.agreed.for(params[:id]).with_profiles
@profiles = @ratings.collect(&:profile)

3.0

@ratings = OpinionRating.agreed.for(params[:id]).includes(:profile)
@profiles = @ratings.collect(&:profile)

이 모든 것의 결론은 이제 쉽게 페이지를 매길 수 있다는 것입니다.

@ratings = @ratings.paginate(:page => params[:page])

Rails 4.x 업데이트 : 거의 동일 :

scope :agreed, ->{ where agreed: true }

def self.for(id)
  joins(:opinion).where(opinion: { id: id })
end 

새로운 Rails의 경우 페이지 매김을 위해 kaminari선호합니다 .

@ratings = @ratings.page(params[:page])

gem will_paginate은 ActiveRecord 쿼리와 배열 모두에 페이지를 매 깁니다.

list = OpinionRating.where(:opinion_id => params[:id]).includes(:profile).paginate(:page => params[:page])
@agree_list = list.map(&:profile)

If you don't want to use the config file or are having trouble with it, you can also just ensure you return an ActiveRecord::Relation instead of an array. For instance, change the agree_list to be a list of user ids instead, then do an IN on those ids to return a Relation.

def agree_list
  list = OpinionRating.find_all_by_opinion_id(params[:id])
  @agree_id_list = []
  list.each do |r|
    user = Profile.find(r.profile_id)
    @agree_id_list << user.id
  end
  @agree_list = User.where(:id => @agree_id_list) 
end

This is inefficient from a database perspective, but it's an option for anybody having issues with the will_paginate config file.


I took advantage of rails associations, and came up with a new method:

def agree_list
  o = Opinion.find(params[:id])
  @agree_list = o.opinion_ratings(:conditions => {:agree => true}, :order => 'created_at DESC').paginate :page => params[:page]
rescue ActiveRecord::RecordNotFound
  redirect_to(profile_opinion_path(session[:user]))
end

In my view I looked up the profile like so:

<% @agree_list.each do |rating| %>
  <% user = Profile.find(rating.profile_id) %>
<% end %>

Please post up if there's a better way to do this. I tried to use the named_scope helper in the OpinionRating model with no luck. Here's an example of what I tried, but doesn't work:

named_scope :with_profile, lambda {|id| { :joins => [:profile], :conditions => ['profile_id = ?', id] } }

That seemed like the same as using the find method though.

Thanks for all the help.


I am using rails 3 ruby 1.9.2. Also, I am just starting app, so no css or styles included.

Install will_paginate:

gem install will_paginate

Add to Gemfile and run bundle.

Controller

class DashboardController < ApplicationController
    include StructHelper

    def show
        @myData =structHelperGet.paginate(:page => params[:page])
    end

end

module StructHelper queries a service, not a database. structHelperGet() returns an array of records.

Not sure if a more sophisticated solution would be to fake a model, or to grab the data every so often and recreate a sqllite table once in a while and have a real model to query. Just creating my first rails app ever.

View

<div id="Data">
                <%= will_paginate @myData%>
                    <table>
                    <thead>
                    <tr>
                    <th>col 1</th>
                    <th>Col 2</th>
                    <th>Col 3</th>
                    <th>Col 4</th>
                    </tr>
                    </thead>
                    </tbody>
                    <% @myData.each do |app| %>
                        <tr>
                           <td><%=app[:col1]%> </td>
                           <td><%=app[:col2]%> </td>
                           <td><%=app[:col3]%> </td>
                           <td><%=app[:col4]%> </td>
                        </tr>

                    <% end %>
                    </tbody>
                    </table>
                <%= will_paginate @myData%>
                </div>

This will give you pagnation of the default 30 rows per page.

If you have not read http://railstutorial.org yet, start reading it now.


You can implement pagination even without any gem.I saw this How do I paginate an Array?. Simple implementation in kaminari gems doc. Please see the below example which i got from kaminari gems doc

arr = (1..100).to_a
page, per_page = 1, 10
arr[((page - 1) * per_page)...(page * per_page)] #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
page, per_page = 2, 10
arr[((page - 1) * per_page)...(page * per_page)] #=> [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

참고URL : https://stackoverflow.com/questions/4352895/ruby-on-rails-will-paginate-an-array

반응형