Jestem nowy w Railsach ... uśmiechnij sięRailsy: "Następny post" i "Poprzedni post" w moim widoku pokazu, jak?
W aplikacji do blogu chcę umieścić link "Poprzedni wpis" i link "Następny wpis" u dołu widoku pokazu.
Jak to zrobić?
Dzięki!
Jestem nowy w Railsach ... uśmiechnij sięRailsy: "Następny post" i "Poprzedni post" w moim widoku pokazu, jak?
W aplikacji do blogu chcę umieścić link "Poprzedni wpis" i link "Następny wpis" u dołu widoku pokazu.
Jak to zrobić?
Dzięki!
Jeśli każdy tytuł jest wyjątkowy i trzeba alfabetycznej, spróbuj tego w modelu 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
Następnie można utworzyć łącze do tych w widoku.
<%= link_to("Previous Post", @post.previous_post) if @post.previous_post %>
<%= link_to("Next Post", @post.next_post) if @post.next_post %>
Niewygodne, ale powinno Cię do siebie zbliżyć. Możesz zmienić numer title
na dowolny unikalny atrybut (created_at
, id
itp.), Jeśli potrzebujesz innej kolejności sortowania.
Naprawdę wystarczy uruchomić 2 zapytania, po jednym dla każdego z "prev" i "next". Załóżmy, że masz kolumnę created_at.
Psuedo-code:
# 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
Oczywiście "this_post" jest obecny postu.
Jeśli twoje posty są przechowywane z kolumną auto_increment i nie korzystasz ponownie z identyfikatorów, możesz po prostu użyć kolumny id w miejsce created_at - kolumna id powinna już być zindeksowana. Jeśli chcesz użyć kolumny created_at, to na pewno chcesz mieć indeks w tej kolumnie.
będziesz potrzebował zamówienie, jak również ... –
Tak, masz rację, zamówienia przez to potrzebne. Zaktualizowałem moją odpowiedź. –
thak you !, ale jeśli potrzebujesz wykryć następny lub poprzedni alfabetyczny: tytuł postu? – pollinoco
Podaruj klej will_paginate spróbować. Zapewnia wszystkie funkcje potrzebne do tworzenia stronicowania wpisów w postach. uczyć się here zbyt
Możesz również spojrzeć na kod here, jeśli chcesz dodać następny i poprzedni przycisk.
will_paginate jest kiepskim rozwiązaniem tego problemu. Gdy wyświetlasz post, masz do czynienia z konkretnym wpisem, a nie z kolekcją. –
Tak to zrobiłem. Po pierwsze, dodać kilka named scopes do modelu 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
Note użycie opcji :select
do ograniczenia pola, ponieważ prawdopodobnie nie chcą odzyskać w pełni wypełnione Post
instancji tylko do pokazywania linków .
Wtedy w moim posts_helper
mam tej metody:
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
jestem pewien, że to może być refactored być mniej gadatliwy, ale intencja jest jasna. Oczywiście twoje wymagania dotyczące oznaczania będą inne niż moje, więc nie możesz na przykład użyć listy nieuporządkowanej.
Ważną rzeczą jest użycie instrukcji if
, ponieważ jeśli jesteś w pierwszym poście, to nie będzie żadnego poprzedniego postu i na odwrót, jeśli jesteś w ostatnim poście, to nie będzie następnego postu.
Wreszcie, po prostu wywołać metodę pomocnika z widoku:
<%= sidebar_navigation_links %>
Cześć John, dziękuję za odpowiedź ... ale mam problem ... Jeśli zniszczę post, stracę kolejny identyfikator i nie wiem, kto jest następny post lub poprzedni post, ponieważ Post.find_by_id (id - 1,: select => 'title, slug etc ...') innym problemem jest to, że nie mam bezpośredniego łącza i nawiguję w tym momencie przez id, ale jeśli zmienię ": href => previous_post.permalink "przez": href => previous_post.id " the href = emty :) Czy możesz mi pomóc? dzięki jeszcze raz! – pollinoco
Użyłem metod modeli jak poniżej, aby uniknąć problemu, w którym id + 1 nie istnieje, ale id + 2 ma.
def previous
Post.where(["id < ?", id]).last
end
def next
Post.where(["id > ?", id]).first
end
W moim kodu widoku, po prostu to zrobić:
- if @post.previous
= link_to "< Previous", @post.previous
- if @post.next
= link_to "Next >", @post.next
Moja metoda pozwala na automatyczne stosowanie modelowych zasięgów. Na przykład możesz wyświetlać tylko posty "opublikowane".
W modelu:
def self.next(post)
where('id < ?', post.id).last
end
def self.previous(post)
where('id > ?', post.id).first
end
W widoku
<%= link_to 'Previous', @posts.previous(@post) %>
<%= link_to 'Next', @posts.next(@post) %>
W kontrolerze
@photos = Photo.published.order('created_at')
Associated rspec testy:
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
Uwaga: po pierwszym/ostatnim poście w kolekcji pojawią się drobne problemy. Polecam przeglądarkę widoku, aby warunkowo wyświetlała poprzedni lub następny przycisk tylko wtedy, gdy istnieje.
Stworzyłem klejnot proximal_records
specjalnie do tego rodzaju zadań i działa on na każdym dynamicznie tworzonym zakresie w twoim modelu.
https://github.com/dmitry/proximal_records
przykład podstawowa:
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
Dziękujemy! jest doskonale! :) – pollinoco
@Sam, tak, dlatego powiedziałem "jeśli każdy tytuł jest unikalny". – ryanb
Przepraszam Ryan, muszę być ślepy, twoje może: conditions => ["title>? And id>?", Title, id] do obejścia. dodanie indeksu na tytuł jest tu krytyczne, chyba że jest to aplikacja zabawkowa. –