2011-03-27 55 views
8

我的應用有照片,用戶可以搜索符合特定條件的照片。我們先來說說照片用戶搜索的標籤,而我們得到的東西是這樣的:Rails:上一個查詢的上一個和下一個記錄

@results = Photo.tagged_with('mountain') 

現在,@results將是一個標準的ActiveRecord查詢與多個記錄。這些將顯示在網格中,然後用戶可以點擊照片。這將使用戶執行photos#show操作。

因此,可以說用戶搜索某物,應用程序找到5條記錄,[1,2,3,4,5],用戶點擊照片#3。

photo#show頁面上,我希望能夠顯示「下一張照片」,「上一張照片」和「返回搜索」。

唯一的另一個限制是,如果用戶直接瀏覽照片(通過另一個頁面或書籤等),則不會有邏輯的「下一張」和「上一張」照片,因爲沒有查詢將他們引導至該照片,因此在這種情況下,該模板根本不應呈現與查詢相關的內容。

所以,我一直在想如何做這種事情,我真的沒有太多好主意。我想我可以做一些事情,比如在會話中存儲查詢,以便能夠回到它,但我不知道如何找到顯示在所選照片的​​左側和右側的照片。

有沒有人有任何如何做這種事情的例子?

+0

[鋼軌可能重複:「下後「和」普雷維奧我們張貼「鏈接在我的節目視圖,如何?](http://stackoverflow.com/questions/1275963/rails-next-post-and-previous-post-links-in-my-show-view-how- to) – 2014-04-20 11:14:52

回答

11

所以,大量的試驗和錯誤之後,這裏是我想出了:

在我的照片模式:

# NEXT/PREVIOUS FUNCTIONALITY 
def previous(query) 
    unless query.nil? 
    index = query.find_index(self.id) 
    prev_id = query[index-1] unless index.zero? 
    self.class.find_by_id(prev_id) 
    end 
end 

def next(query) 
    unless query.nil? 
    index = query.find_index(self.id) 
    next_id = query[index+1] unless index == query.size 
    self.class.find_by_id(next_id) 
    end 
end 

這個方法從搜索或特定返回下一個和以前的記錄通過接受這些記錄ID的數組來查看文件夾視圖。我生成,創建一個查詢視圖的任何控制器認爲ID(即搜索頁面和文件夾頁面瀏覽):

所以,舉例來說,我的搜索控制器包含:

def search 
    @search = @collection.photos.search(params[:search]) 
    @photos = @search.page(params[:page]).per(20) 
    session[:query] = @photos.map(&:id) 
end 

然後是照片顯示#操作包含:

if session[:query] 
    @next_photo = @photo.next(session[:query]) 
    @prev_photo = @photo.previous(session[:query]) 
end 

最後,我認爲包含:

- if @prev_photo || @next_photo 
    #navigation 
    .header Related Photos 
    .prev 
     = link_to image_tag(@prev_photo.file.url :tenth), collection_photo_path(@collection, @prev_photo) if @prev_photo 
     - if @prev_photo 
     %span Previous 
    .next 
     = link_to image_tag(@next_photo.file.url :tenth), collection_photo_path(@collection, @next_photo) if @next_photo 
     - if @next_photo 
     %span Next 

現在,事實證明這個作品中經常瀏覽的情況不錯 - 但有一個疑難雜症,我還沒有固定的:

從理論上講,如果用戶搜索一個視圖,然後跳轉到他們所產生的照片會話中的查詢。如果出於某種原因,他們然後直接瀏覽(通過URL或書籤)到另一張屬於先前查詢的照片,查詢將會保留在會話中,並且相關照片鏈接仍將在第二張照片上可見 - 即使他們不應該在通過書籤加載的照片上。

但是,在現實生活中,這種情況實際上很難重新創建,而且代碼目前運行良好。在某個時候,當我爲剩下的那個問題想出一個很好的解決方案時,我會發布它,但是現在如果有人使用這個想法,請注意可能存在。

+0

您可以通過將持久查詢的id放入下一個/上一個鏈接的url以及搜索頁面中的鏈接來解決您的_gotcha_。這樣,如果您看到ID並且它與最後一個持續查詢匹配,則顯示下一個/上一個按鈕。如果由於用戶輸入了URL或以另一種方式到達了頁面,ID不在那裏,請不要顯示按鈕。 – 2011-04-13 20:19:05

+0

@Brian:哦!這是一個很酷的想法,我會努力實現這樣的事情! – Andrew 2011-04-13 20:36:48

+0

非常感謝發佈這個,它真的很有用。 – snowangel 2011-07-01 07:17:59

0

你可以看看在ActsAsAdjacent做什麼:

named_scope :previous, lambda { |i| {:conditions => ["#{self.table_name}.id < ?", i.id], :order => "#{self.table_name}.id DESC"} } 
named_scope :next, lambda { |i| {:conditions => ["#{self.table_name}.id > ?", i.id], :order => "#{self.table_name}.id ASC"} } 

從本質上講,他們的作用域(預Rails 3的語法)來檢索具有較小的ID記錄/大於記錄的ID你傳入。

由於它們是作用域,因此可以用.first鏈接前一個以獲取在當前項目之前創建的第一個項目和.tagged_with('mountain')。首先獲取第一個標記爲'山'。

2

安德魯,你的方法不通用,不保證正確的結果。有更好的方法來做到這一點。 在你的模型:

def previous 
    Photo.where('photos.id < ?', self.id).first 
end 

def next 
    Photo.where('photos.id > ?', self.id).last 
end 

而且在訪問量:

- if @photo.previous 
    = link_to 'Previous', @photo.previous 
- if @photo.next 
    = link_to 'Next', @photo.next 
+0

這不*做我想做的事情。我不只是想要下一張照片,我希望來自特定用戶最近搜索結果的下一張照片。我相信我的方法並不完美,我列出了我最知名的「疑難雜症」,但它在我的應用程序中按需要工作。 – Andrew 2012-03-01 03:03:14

+1

它沒有做他想做的事,但它對我來說是完美的:) – Arcolye 2012-03-14 08:49:09

+0

對我來說,使用Rails 4這個工作並不合適。你的「下一個」給了我「最後」和「之前」給我的第一個。 – 2014-02-14 23:38:59

1

一個我編寫的名爲Nexter寶石會爲你。

您傳遞一個AR Scope組合(即ActiveRelation)加上當前對象/記錄,Nexter將檢查order子句以構建將獲取before/previous和/ after記錄的sql。

基本上它着眼於ActiveRelation#order_values爲了(A,B,C),並隆重推出:

# pseudo code 
where(a = value_of a AND b = value of b AND c > value of c).or 
where(a = value_of a AND b > value of b).or 
where(a > value of a) 

這只是它的要點。它也與關聯值一起工作,並且聰明地找到前一部分的反向值。爲了保持你的搜索狀態(或範圍組合),你可以使用另一個像siphon的lib,ransack,has_scope等...

下面是來自自述一個working example

模型:

class Book 
    def nexter=(relation) 
    @nexter = Nexter.wrap(relation, self) 
    end 

    def next 
    @nexter.next 
    end 

    def previous 
    @nexter.previous 
    end 
end 

控制器

class BookController 
    before_filter :resource, except: :index 

    def resource 
    @book_search = BookSearch.new(params[:book_search]) 

    @book ||= Book.includes([:author]).find(params[:id]).tap do |book| 
     book.nexter = siphon(Book.scoped).scope(@book_search) 
    end 
    end 
end 

的視圖:

<%= link_to "previous", book_path(@book.previous, book_search: params[:book_search]) %> 
<%= link_to "collection", book_path(book_search: params[:book_search]) %> 
<%= link_to "next", book_path(@book.next, book_search: params[:book_search]) 
``` 
相關問題