web-dev-qa-db-ja.com

Ruby on Rails will_paginate array

誰かがオブジェクトの配列で 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

ありがとうございました

70
Brian

will_paginate 3.0は、新しいActiveRecord::Relation in Rails3。したがって、デフォルトではリレーションに対してのみpaginateを定義します。それでも配列を使用できますが、Railsその部分を要求する。

config/initializers(私はwill_paginate_array_fix.rb)、 これを追加

require 'will_paginate/array'

その後、配列で使用できます

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

_Array#from_を使用してページネーションをシミュレートすることもできますが、実際の問題は、Arrayを使用しないことです。

これは、ActiveRecord Associationsの目的です。このガイドを注意深く読んでください。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のリストを反復してユーザーを手動で収集する代わりに、Railsを_named_scope_またはscopeを使用してこれを行うことができますre using 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
_

いずれの場合でも、OpinionRatingsモデルでfor(id)を呼び出して、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])
_
9
Adam Lassek

宝石will_paginateは、ActiveRecordクエリと配列の両方をページ分割します。

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

構成ファイルを使用したくない場合や問題がある場合は、配列ではなくActiveRecord :: Relationを返すようにすることもできます。例えば、agree_listをユーザーIDのリストに変更し、それらのIDでINを実行して関係を返します。

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構成ファイルに問題がある人にとってはオプションです。

1
mcclaskc

私はRails 3 Ruby 1.9.2。を使用しています。また、アプリを起動しているだけなので、CSSやスタイルは含まれていません。

will_paginateをインストール:

gem install will_paginate

Gemfileに追加してバンドルを実行します。

コントローラー

class DashboardController < ApplicationController
    include StructHelper

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

end

モジュールStructHelperは、データベースではなくサービスを照会します。 structHelperGet()は、レコードの配列を返します。

より洗練されたソリューションがモデルを偽造するのか、データを時々取得して、時々sqlliteテーブルを再作成し、実際のモデルを照会するのかどうかはわかりません。私の最初のRailsアプリを作成するだけです。

表示

<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 をまだ読んでいない場合は、今すぐ読み始めてください。

0
mpechner

Gemがなくてもページネーションを実装できます。これを見ました 配列のページネーションはどうすればいいですか? 。 kaminari gems docでの簡単な実装。 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]
0
Jose Kj

Railsアソシエーションを利用して、新しいメソッドを思い付きました:

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

これを行うより良い方法があれば投稿してください。 OpinionRatingモデルでnamed_scopeヘルパーを使用しようとしましたが、うまくいきませんでした。ここに私が試したものの例がありますが、動作しません:

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

ただし、findメソッドを使用するのと同じように見えました。

すべての助けてくれてありがとう。

0
Brian