2010-12-04 2 views
66

Мне было интересно, может ли кто-нибудь объяснить, как использовать will_paginate на массиве объектов?Ruby on Rails will_paginate array

Например, на моем сайте у меня есть раздел мнения, где пользователи могут оценивать свои мнения. Вот метод, который я написал, чтобы собрать пользователей, которые оценили свое мнение:

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 

Спасибо

+1

Приехав сюда из поиска Google для «массива paginate rails», я хотел поделиться с другими посетителями, что [kaminari] (https://github.com/amatsuda/kaminari) является альтернативой pagination рельсов, , Эффективно обрабатывает массивы. – 2015-01-28 17:50:12

ответ

201

will_paginate 3.0 предназначен для использования в новых ActiveRecord::Relation в Rails 3, поэтому он определяет paginate только по отношениям по умолчанию. Он все еще может работать с массивом, но вы должны сказать, что рельсы требуют эту часть.

В файле в вашем config/initializers (я использовал will_paginate_array_fix.rb), добавьте

require 'will_paginate/array' 

Затем вы можете использовать на массивах

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

Вы можете использовать Array#from для имитации пагинацию, но реальная проблема в том, что вы не должны использовать Array вообще.

Это то, что предназначено для. Вы должны внимательно прочитать это руководство, есть много полезных вещей, которые вам понадобятся, если вы разрабатываете приложения 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 

Очень важно, чтобы ваша схема базы данных следующие соответствующие соглашения об именах или все это сломается. Убедитесь, что вы создаете свои таблицы с помощью Database Migrations вместо того, чтобы делать это вручную.

Эти ассоциации создадут помощников на ваших моделях, чтобы сделать поиск намного проще. Вместо того, чтобы повторять список OpinionRatings и собирать пользователей вручную, вы можете сделать Rails сделать это для вас с использованием named_scope или scope в зависимости от того, используете ли вы Rails 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 модели и передать его идентификатор:

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.х: более или менее то же самое:

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

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

Хотя для нового Rails моего предпочтение kaminari для пагинации:

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

Ну, ассоциации - это таблица. Мнение has_many: opinion_ratings, и принадлежит_to: мнение. Мнение понравилось таблице «Профиль» через отношения «многие ко многим» с таблицей соединений «Категории». С помощью этой настройки вы знаете, как это изменит код, упомянутый выше? – Brian 2010-12-04 10:25:09

+0

@Brian Я обновил свой пример, но я не могу быть уверен, пока вы не покажете мне свои классы моделей. – 2010-12-04 10:38:06

4

will_paginate Жемчужина отформатируют оба запрос ActiveRecord и массивы.

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

я воспользовался рельсам ассоциаций, и придумали новый метод:

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 

На мой взгляд, я посмотрел профиль, как так:

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

Пожалуйста развесить если есть лучший способ сделать это. Я попытался использовать помощник named_scope в модели OpinionRating без везения. Вот пример того, что я пробовал, но не работает:

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

Это казалось таким же, как с помощью метода найти хотя.

Спасибо за помощь.

0

Я использую рельсы 3 ruby ​​1.9.2. Кроме того, я просто запускаю приложение, поэтому никаких скинов или стилей не было.

Установка will_paginate:

камень установить will_paginate

Добавить в Gemfile и запустить пакет.

Контроллер

class DashboardController < ApplicationController 
    include StructHelper 

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

end 

модуль StructHelper запрашивает услугу, а не базы данных. structHelperGet() возвращает массив записей.

Не уверен, что более сложное решение будет заключаться в подделке модели или для сбора данных так часто и заново создать таблицу sqlite время от времени и иметь реальную модель для запроса. Просто создайте мое первое приложение для рельсов.

Посмотреть

<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> 

Это даст вам вёрстка по умолчанию 30 строк на каждой странице.

Если вы еще не читали http://railstutorial.org, начните читать его сейчас.

1

Если вы не хотите использовать конфигурационный файл или возникают проблемы с ним, вы также можете просто обеспечить возврат ActiveRecord :: Relation вместо массива. Например, измените список_согласования как список идентификаторов пользователей, а затем введите IN для этих идентификаторов, чтобы вернуть 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 

Это неэффективно с точки зрения базы данных, но это вариант для всех, кто есть проблемы с will_paginate конфигурационного файла.

Смежные вопросы