2017-05-04 44 views
0

我有什麼

我現在有喜歡使用路徑傭工非默認的屬性,而不是:ID

get 'book/:id' => 'books#show', as: :book 

的代碼創建一個URL路徑是:

book_path @book 

在控制器:

@book = Book.find(params[:id]) 

到現在爲止還挺好。現在,這個ID顯然是內部的ActiveRecord或數據庫主鍵。

我想要什麼

相反,我會(在這個例子虛構)使用書號代替。我可以這樣做:

get 'book/:isbn' => 'books#show', as: :book 
book_path(isbn: @book.isbn) 
@book = Book.find_by(isbn: params[:isbn]) 

這有點冗長;我希望在整個應用程序中使用這個模型的約定「isbn」,而且沒有人需要關心它。所以,我希望我的3條線看起來像這樣:

get 'book/:isbn' => 'books#show', as: :book 
book_path @book # (!) 
@book = Book.find(params[:isbn]) # (!) 

是否可以配置路線以便我的願望成真?顯然,這應該自動工作無處不在,至少對於用戶在URL中看到ISBN的GET請求。

如果重要,#isbn屬性不是通常意義上的主鍵,但可以保證表中只有一個特定ISBN的記錄。所以至少這部分主鍵合約已經完成。

+0

你檢查了[to_param](https://apidock.com/rails/ActiveRecord/Integration/to_param)方法嗎? – Sajan

+0

我沒有!謝謝,這很好,解決了兩者中更緊迫的問題。事後看來,我想我更喜歡'#find',所以堅持內部ID,反正。如果你創建一個迷你答案,你會得到我的接受。 – AnoE

回答

0

要覆蓋Rails的默認:id參數,你可以使用to_param方法:

class Book < ActiveRecord::Base 
    def to_param # overridden 
    isbn 
    end 
end 

並在控制器:

book = Book.find_by(isbn: '123456') 

如果你沒有任何問題,使用任何寶石吧,那麼我建議你應該看看friendly_id寶石。這在這種情況下做得很好。

0

在你routes.rb,使用匹配匹配/book/:isbnbook#show

match '/book/:isbn' => 'book#show', via: :get, as: :show_book 

在你book.rb,您可以覆蓋爲了find方法查找基於ISBN,而不是ID。沿着線的東西:

def self.find(*args) 
    c = Book.select("id").find_by(name: args[0]) 
    args[0] = c.id 
    super(args) 
end 

這將首先isbn找到並使用id,它會調用 find方法。 (我沒有測試過這個,你將不得不修改它以使它與多個isbn s一起工作)

但是我不確定這是否被推薦以及它會出現什麼警告。

相反,你爲什麼不使用find_by_isbn[params[:isbn]]?它比find_by(:isbn, params[:isbn])更具可讀性。