2012-10-08 72 views
0

我正在返回我幾個月前編寫的應用程序,並嘗試進行一些小調整。我目前有一個型號Product和一個目錄頁,其中所有產品均使用each循環列出Product中的所有條目。在Rails中自動創建單獨的產品頁面

爲了保證站點的安全,我已將http://.../products/...放在身份驗證登錄名後面,因此只有擁有密碼的用戶才能看到/products/index,編輯產品詳細信息並一次查看一個產品(顯示頁面)。

我現在想從列表中列出的所有產品的頁面鏈接到只有一個產品的詳細信息(即單個產品自己的頁面)。

我知道我可以使用Product ID的查找功能從Product模型中找到產品,但是,我該如何自動爲該產品的商家信息創建明智的網址?

總之,如果我在頁面上列出了10種產品,那麼讓用戶點擊產品並將其路由到名爲http://..../shop/specific_products_name的頁面的最佳方式是什麼?我已閱讀了一下週圍,它似乎to_param可能會有一定的好處,但我努力工作了創建這些頁面

感謝您的時間的合理手段

回答

1

這裏有一個基本的,常規的控制器設置:

首先,這裏的路線快捷語法:

# 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 

在路由文件行給了我們這些航線(其中包括):

  • /productsproducts_controller#index
  • /products/:idproducts_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) 
+0

非常感謝您的非常全面的答案,這正是您所說的。這是非常有用的,但並不完全是我所希望的,因此我有幾個關於查詢的問題......(希望你不介意) 1.解決方案A很好,理想情況下我想'/'而不是'''在'id後面,但是這會導致錯誤? 2.用戶仍然需要登錄才能以這種方式查看產品,這不是我的目標,我目前在我的「產品控制器」中有'before_filter:authenticate',我可以僅禁用顯示頁面的身份驗證嗎? 3.我可以縮小網址以便'/ products /'不在嗎? – Texas

+0

哈哈,很酷。我顯然有太多的咖啡,一定是誤解了你的問題的癥結所在。我會編輯我的答案。 – danneu

+0

您可以使用'before_filter:authenticate禁用before過濾器,但以下情況除外::show'或'before_filter:authenticate,only :: index'。你也可以傳入一系列動作,比如'only:[:show,:new]'。 http://guides.rubyonrails.org/action_controller_overview.html#filters – danneu

相關問題