這裏有一個基本的,常規的控制器設置:
首先,這裏的路線快捷語法:
# config/routes.rb
...
resources :products
...
下面是加載在上index
,只是一個產品的所有產品控制器210。
# app/controllers/products_controller.rb
class ProductsController
def index
@products = Product.all
end
def show
@product = Product.find(params[:id])
end
end
在路由文件行給了我們這些航線(其中包括):
/products
去products_controller#index
/products/:id
去products_controller#show
使用參數[:ID]設置爲給定數
以最少的工作量獲得一個漂亮的URL最簡單的方法是,如您所查看,覆蓋to_param
。
to_param
是Rails用來將模型轉換爲url/request中的表示形式。
默認情況下,它是這樣的:
class Product
def to_param
self.id
end
end
因此,當滑軌上to_param
的結果做了Product.find(),find()
把它與to_i
整數。
如果params[:id]
是"24"
,然後Product.find(params[:id])
「24」 轉換爲整數24。
但考慮如何to_i
作品與其他的例子:
"100".to_i #=> 100
"100-flux-capacitor-2000".to_i #=> 100
換句話說,如果一個產品我們參數表示是"#{id}-the-product-name"
,Product.find(params[:id])
仍然可以工作,即使我們的產品#顯示的URL看起來像/products/56-ford-taurus
。
一兩件事:
"I love the Ford Taurus".parameterize #=> "i-love-the-ford-taurus"
解決方案A
您的問題最簡單的辦法是重寫to_param這樣的:
class Product
def to_param
"#{id}-#{name.parameterize}"
end
end
這種方法的好處是,你改變產品模型中的一個方法以及Just Works的其他代碼。
的缺點是,你的URL看起來像:
/products/56-ford-taurus
相反的:
/products/ford-taurus
溶液B
如果你想在後面的例子中,你可以保持在一個slug
列產品表。
例子:
Product
id: 58
name: Ford Taurus
slug: ford-taurus
然後,你可以重寫to_param這樣的:
class Product
def to_param
slug
end
end
現在,則params [:編號]看起來像 「福特金牛座」。
Product.find("ford-taurus")
將不再工作,因爲find()想要一個整數,所以你可以用Product.find_by_slug(params[:id])
替換Product.find(params[:id])
。
你只需要確保每個產品都有獨特的slu slu。
你還可以用像自動蛞蝓創建過程:
class Product
before_create :make_slug
private
def make_slug
self.slug = name.parameterize
end
end
這樣,你只需要設置在創建產品的名稱,保存它,和它的蛞蝓將成爲友好的URL「什麼-the-產品名稱是」。
- 正面:您的網址現在只包含產品名稱,沒有醜陋的產品ID。
- 不利因素:改變產品的slu will會破壞URL,這就是爲什麼我的before_filter示例只能在創建時設置slu and,而不是在任何時候保存產品。
現在,Rails會產生你想要的,你可以生成這樣的視圖鏈接到這些產品的那種網址:
# This would be in views/index.html.erb
<% @products.each do |product| %>
<%= link_to product.name, product %>
<% end %>
將產品這種HTML的每個產品的:
<a href="/products/56-ford-taurus">Ford Taurus</a> (if you used Solution A)
<a href="/products/ford-taurus">Ford Taurus</a> (if you used Solution B)
非常感謝您的非常全面的答案,這正是您所說的。這是非常有用的,但並不完全是我所希望的,因此我有幾個關於查詢的問題......(希望你不介意) 1.解決方案A很好,理想情況下我想'/'而不是'''在'id後面,但是這會導致錯誤? 2.用戶仍然需要登錄才能以這種方式查看產品,這不是我的目標,我目前在我的「產品控制器」中有'before_filter:authenticate',我可以僅禁用顯示頁面的身份驗證嗎? 3.我可以縮小網址以便'/ products /'不在嗎? – Texas
哈哈,很酷。我顯然有太多的咖啡,一定是誤解了你的問題的癥結所在。我會編輯我的答案。 – danneu
您可以使用'before_filter:authenticate禁用before過濾器,但以下情況除外::show'或'before_filter:authenticate,only :: index'。你也可以傳入一系列動作,比如'only:[:show,:new]'。 http://guides.rubyonrails.org/action_controller_overview.html#filters – danneu