2009-08-14 11 views

答えて

41

各タイトルはユニークであり、あなたはアルファベットが必要な場合は、お使いのPostモデルでこれを試してみてください。

def previous_post 
    self.class.first(:conditions => ["title < ?", title], :order => "title desc") 
end 

def next_post 
    self.class.first(:conditions => ["title > ?", title], :order => "title asc") 
end 

ビュー内のものにリンクすることができます。

<%= link_to("Previous Post", @post.previous_post) if @post.previous_post %> 
<%= link_to("Next Post", @post.next_post) if @post.next_post %> 

未テストですが、あなたに近づくはずです。別のソート順が必要な場合は、titleを一意の属性(created_atidなど)に変更できます。

+0

ありがとうございました!!!!完璧です! :) – pollinoco

+0

@Sam、そう、私は "それぞれのタイトルが一意であるなら"と言ったのです。 – ryanb

+0

申し訳ありませんRyan、私は盲目的になるはずです:条件=> ["title>?とid>?"、title、id]は回避する必要があります。タイトルにインデックスを追加することは、そのおもちゃのアプリがない限りここでは重要なことです。 –

-1

"prev"と "next"のそれぞれに1つずつ、2つのクエリを実行するだけです。 created_atカラムがあると仮定します。

擬コード:もちろん

# get prev 
select * from posts where created_at < #{this_post.created_at} order by created_at desc limit 1 

# get next 
select * from posts where created_at > #{this_post.created_at} order by created_at desc limit 1 

現在のポストである "this_post"。

あなたの投稿がauto_incrementカラムに保存されていて、IDを再利用しない場合は、created_atの代わりにidカラムを使用するだけで済みます。idカラムはすでに索引付けされているはずです。 created_atカラムを使用する場合は、そのカラムにインデックスを置くことが間違いないでしょう。

+1

あなたが同様で順番を必要としています... –

+0

うんは、あなたは正しい、によって順序が必要とされています。私は自分の反応を更新しました。 –

+0

あなたを賞賛してください!しかし、必要ならば、次のまたは前のアルファベット順を検出してください: – pollinoco

0

will_paginateを試してみてください。投稿エントリのページを設定するために必要なすべての機能を提供します。 learn here too

次のボタンと前のボタンを追加したい場合は、hereも参照できます。

+3

will_paginateはこの問題にはあまり適していません。投稿を表示しているときは、コレクションではなく個々の投稿を扱っています。 –

1

これが私のやり方です。まず、あなたのPostモデルにnamed scopesのカップルを追加します:あなたはおそらくちょうどリンクを示すためにフル実装Postインスタンスを取得したくないので

def previous 
    Post.find_by_id(id - 1, :select => 'title, slug etc...') 
end 

def next 
    Post.find_by_id(id + 1, :select => 'title, slug etc...') 
end 

は、フィールドを制限する:selectオプションの使用に注意してください。

はその後、私のposts_helperに、私はこの方法があります:

def sidebar_navigation_links 
    next_post = @post.next 
    previous_post = @post.previous 
    links = '' 
    if previous_post 
    links << content_tag(:h3, 'Previous') 
    links << content_tag(:ul, content_tag(:li, 
           content_tag(:a, previous_post.title, 
              :href => previous_post.permalink))) 
    end 
    if next_post 
    links << content_tag(:h3, 'Next', :class => 'next') if previous_post 
    links << content_tag(:h3, 'Next') if previous_post.nil? 
    links << content_tag(:ul, content_tag(:li, 
           content_tag(:a, next_post.title, 
              :href => next_post.permalink))) 
    end 
    content_tag(:div, links) 
end 

を、私は、これはそれほど冗長であることをリファクタリングすることができ確信しているが、意図は明確です。明らかにマークアップの要件は私のものとは異なるので、たとえば、順序付けられていないリストの使用を選択することはできません。

重要なことは、ifステートメントを使用することです。最初の投稿をしていれば、前の投稿はなく、逆に、最後の投稿の場合は次の投稿ではないからです。

最後に、単にあなたのビューからヘルパーメソッドを呼び出します。

<%= sidebar_navigation_links %> 
+0

こんにちはJohnさん、あなたの答えをありがとうございます...しかし、私は問題があります.... 投稿を破棄した場合、私は連続したIDを失い、 Post.find_by_id(id - 1、:select => 'タイトル、スラッグなど...') 他の問題は、私はパーマリンクを持っていないと私はこの時点でIDで移動するが、 href => previous_post.permalink "by:" href => previous_post.id " href = emty :) 私を助けることができますか? もう一度ありがとう! – pollinoco

13

id + 1は存在しないがid + 2は問題を避けるため、次のようなモデル方法を使用しました。私の見解コードで

def previous 
    Post.where(["id < ?", id]).last 
end 

def next 
    Post.where(["id > ?", id]).first 
end 

、私はこれを行う:

- if @post.previous 
    = link_to "< Previous", @post.previous 
    - if @post.next 
    = link_to "Next >", @post.next 
3

私の方法は、あなたが自動的にモデルのスコープを使用できるようになります。たとえば、「公開された」投稿のみを表示することができます。お使いのモデルで

:あなたのコントローラ

@photos = Photo.published.order('created_at') 

関連RSpecのテストで

def self.next(post) 
    where('id < ?', post.id).last 
end 

def self.previous(post) 
    where('id > ?', post.id).first 
end 
あなたのビューで

<%= link_to 'Previous', @posts.previous(@post) %> 
<%= link_to 'Next', @posts.next(@post) %> 

describe '.next' do 
    it 'returns the next post in collection' do 
    fourth_post = create(:post) 
    third_post = create(:post) 
    second_post = create(:post) 
    first_post = create(:post) 

    expect(Post.next(second_post)).to eq third_post 
    end 

    it 'returns the next post in a scoped collection' do 
    third_post = create(:post) 
    decoy_post = create(:post, :published) 
    second_post = create(:post) 
    first_post = create(:post) 

    expect(Post.unpublished.next(second_post)).to eq third_post 
    end 
end 

describe '.previous' do 
    it 'returns the previous post in collection' do 
    fourth_post = create(:post) 
    third_post = create(:post) 
    second_post = create(:post) 
    first_post = create(:post) 

    expect(Post.previous(third_post)).to eq second_post 
    end 

    it 'returns the previous post in a scoped collection' do 
    third_post = create(:post) 
    second_post = create(:post) 
    decoy_post = create(:post, :published) 
    first_post = create(:post) 

    expect(Post.unpublished.previous(second_post)).to eq first_post 
    end 
end 

注:コレクションの最初/最後の投稿に行くと、小さな問題が発生します。前または次のボタンが存在する場合のみ条件付きで表示するためのビューヘルパーを推奨します。

0

私は特にこの種のタスクのために宝石proximal_recordsを作成しました。これは、モデル内の動的に作成されたスコープで動作します。

https://github.com/dmitry/proximal_records

Basicの例:

class Article < ActiveRecord::Base 
    include ProximalRecords 
end 


scope = Article.title_like('proximal').order('created_at DESC, title ASC') 
current_record = scope.to_a[5] 
p, n = current_record.proximal_records(scope) # will find record 5 and 7 
関連する問題