如何为Rails应用程序创建应用程序范围的slug路由?

我正在研究的Rails应用程序中有许多不同的模型。 我已经看到许多网站使用应用程序范围的slug路由方法。 这是什么意思?

http://example.com/nick-oneill <-- This points to a User object http://example.com/facebook <-- This points to a Company object http://example.com/developers <-- This points to the users#index page 

我知道to_param并在应用程序中创建读者友好的slug,但是我不知道有一种方法可以为各种对象提供根级别的slu .. 您可以认为这类似于Facebook的Graph API:有不同的对象类型,但它们都存在于https://graph.facebook.com/object-id

任何见解都将非常感谢!

有一种方法可以用freindly_id做到这一点,但我认为友好id的问题是事物是由模型确定的。

如果我真的希望在整个网站上进行阻塞,我会创建一个与我所有模型具有多态关系的slugs表。

Sluggable_type和sluggable_id然后是一个带有完整永久链接/ slug的slug字段。

 +---------------------------------------------+ | sluggable_type | sluggable_id | slug | | user | 13 | users/john | +---------------------------------------------+ 

现在我可以做一个通配符捕获所有路由或在运行时为我的所有slug创建路由,并在更新模型时在这个缓慢的控件下强制路由刷新。

routes.rb

  get "/*segments", :controller => 'slugs', :action => 'dynamicroute' 

现在在你的SlugsController中实现一个类似的方法

 def dynamicroute segments = params[:segments] slugs.find_by_slug(segments) slug.sluggable_type.constantize.find(slug.sluggable_id) #retrive real record #some magic to handle the slugged item maybe redirect to the appropriate #controller or somehow call the show view for that controller end 

要么

routes.rb

 begin Slug.all.each do |s| begin get "#{s.slug}" => "#{s.sluggable_type.demodulize.pluralize.camelize}#show" rescue end end rescue end 

如果您使用第二种方法进行路由,请确保拨打电话

YOUR_APP_NAME::Application.reload_routes!

编辑任何slugged记录后刷新路由表。

我们遇到过类似的问题,我们可能会尝试着这种方法。

我可能会按如下方式处理,至少作为第一遍:

  • 使用friendly_id或类似方法为每个涉及的模型生成slug
  • 连接/([-_a-zA-Z0-9]+)的全能路线并将其指向EntitiesController#show
  • 为指向Users#index /developers建立更高优先级的路由
  • 在EntitiesController #show中:

    @entity = User.find(params[:id]) or Company.find(params[:id]) or raise ActionController::RoutingError.new('Not Found')

  • 然后,根据您获得的实体类型:

    render "VIEW_PATH_BASED_ON_ENTITY_CLASS/show"

我还会从大多数到最不经常访问的顺序排序(首先猜测,然后再使用数据来调整顺序)。

最后,可能很明显,但请确保您正在为每个表中的slug列编制索引,因为您经常会为每个请求执行多次查找。

FWIW我也想知道更好的方法来解决这个问题; 这就是我最初如何解决问题的方法。

我的第一反应是创建一个新的Slug模型。 这个模型有一个多态的belongs_to

 belongs_to :sluggable, :polymorphic => true 

至少这个表会有:

  • value – 或者比这更好的名字。 slu its本身的价值。
  • sluggable_typesluggable_id – 多态外键。

您的公司,用户等型号模型只会有一个slu ::

 has_one :slug 

这给了我们一些优势:

  • 现在很容易对slug值做出一个独特的约束。 如果slug被保存为所有不同的可缓冲模型的属性,那么您的唯一约束必须检查所有其他可缓冲表的唯一性。 花了很多时间。
  • 路由非常简单,因为您可以使用根级别命名空间之外的常规resource路由。 您可能希望将其保留在路径文件的低端/末端,因此其他更具体的路由优先。 编辑 :这个路由基本上是j_mcnally建议的第一个路由方法。
  • 一个slug的所有逻辑,就像是一个有效的slug,都保留在这个模型中。 关注点的良好分离而非污染表示用户模型。 特别是如果slu children规则对于每个人来说都是一样的。

关于控制器的工作方式,我会选择Kyle所说的并关闭sluggable_type字段来查找要渲染的视图。