0

我正在返回几个月前编写的应用程序并尝试进行一些小的调整。我目前有一个模型Product和一个目录页面,其中所有产品都使用each循环列出Product.

为了尝试保持网站安全,我已经设置http://.../products/...了身份验证登录,因此只有具有密码的用户才能查看/products/index、编辑产品详细信息并一次查看一个产品(显示页面)。

我现在想从列出所有产品的页面链接到只有一个产品详细信息的页面(即单个产品自己的页面)。

我知道我可以Product使用 a 的 find 函数从模型中找到产品Product ID,但是,如何自动为该产品的列表创建合理的 URL?

总之,如果我在一个页面上有 10 种产品的列表,那么让用户点击产品并被路由到名为 的页面的最佳方式是什么http://..../shop/specific_products_name?我已经阅读了一些,看起来to_param可能会有一些好处,但我正在努力寻找一种创建这些页面的明智方法

谢谢你的时间

4

1 回答 1

1

这是一个基本的常规控制器设置:

首先,这是路由快捷方式语法:

# config/routes.rb
...
resources :products
...

这是加载所有产品的控制器,index仅加载一个产品show

# 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#showparams[:id] 设置为给定的数字

如您所见,以最少的工作量获得漂亮 URL 的最简单方法是覆盖to_param.

to_param是 Rails 用来将模型转换为 url/request 中的表示的方法。

默认情况下,它是这样的:

class Product
  def to_param
    self.id
  end
end

因此,当 Rails 对其结果执行 Product.find() 时to_paramfind()将其转换为带有to_i.

如果params[:id]"24"Product.find(params[:id])则将“24”转换为整数 24。

但请考虑如何to_i与其他示例一起使用:

"100".to_i                     #=> 100
"100-flux-capacitor-2000".to_i #=> 100

换句话说,如果我们的 Product 参数表示是"#{id}-the-product-name",Product.find(params[:id])即使我们的 products#show 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

这种方法的好处是您更改了 Product 模型中的一个方法,而您的其余代码只是 Works。

缺点是您的网址看起来像:

/products/56-ford-taurus

代替:

/products/ford-taurus

解决方案 B

如果您想要后一个示例,您可以slug在 Products 表中维护一个列。

例子:

Product
  id: 58
  name: Ford Taurus
  slug: ford-taurus

然后你可以像这样覆盖 to_param:

class Product
  def to_param
    slug
  end
end

现在, params[:id] 看起来像“ford-taurus”。

Product.find("ford-taurus")由于 find() 需要一个整数,因此不再起作用,因此您可以替换Product.find(params[:id])Product.find_by_slug(params[:id]).

你只需要确保每个产品都有一个独特的 slug。

您可以通过以下方式自动化 slug 创建过程:

class Product
  before_create :make_slug

  private
  def make_slug
    self.slug = name.parameterize
  end
end

这样,您只需要在创建时设置产品名称,保存它,它的 slug 将成为 URL 友好的“无论产品名称是什么”。

  • 优点:您的 URL 现在只包含产品名称,没有难看的产品 ID。
  • 不利的一面:更改产品的 slug 会破坏 URL,这就是为什么我的 before_filter 示例仅在创建时设置 slug 而不是在您保存产品时设置。

现在 Rails 将生成您想要的 URL,您可以在如下视图中生成指向这些产品的链接:

# 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)
于 2012-10-08T20:45:34.090 回答