Подтвердить что ты не робот

Rails: ссылки "Next post" и "Previous post" в моем представлении, как?

Я новичок в Rails... smile

В моем блоге я хочу иметь ссылку "Предыдущее сообщение" и ссылку "Следующее сообщение" в нижней части моего представления.

Как это сделать?

Спасибо!

4b9b3361

Ответ 1

Если каждый заголовок уникален и вам нужен алфавит, попробуйте это в своей модели 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_at, id и т.д.), Если вам нужен другой порядок сортировки.

Ответ 2

Я использовал методы модели, как показано ниже, чтобы избежать проблемы, когда 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

Мой метод позволит вам автоматически использовать области модели. Например, вы можете показывать только опубликованные сообщения.

В вашей модели:

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

В вашем контроллере

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

Связанные тесты RSpec:

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

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

Ответ 4

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

Тогда в моем 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 %>

Ответ 5

Дайте will_paginate Попробуй попробовать. Он предоставляет все функции, необходимые для разбивки записей в сообщениях. learn здесь тоже

Вы можете посмотреть здесь, например, код, если вы хотите добавить следующие и предыдущие кнопки.

Ответ 6

Я создал gem proximal_records специально для этой задачи и работает на любой динамически созданной области в вашей модели.

https://github.com/dmitry/proximal_records

Основной пример:

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

Ответ 7

Вам просто нужно запустить 2 запроса, по одному для каждого из "prev" и "next". Предположим, что у вас есть столбец 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 - столбец идентификатора должен быть уже проиндексирован. Если вы хотите использовать столбец created_at, то вы обязательно захотите иметь индекс в этом столбце.