如何为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_type
和sluggable_id
– 多态外键。
您的公司,用户等型号模型只会有一个slu ::
has_one :slug
这给了我们一些优势:
- 现在很容易对slug值做出一个独特的约束。 如果slug被保存为所有不同的可缓冲模型的属性,那么您的唯一约束必须检查所有其他可缓冲表的唯一性。 花了很多时间。
- 路由非常简单,因为您可以使用根级别命名空间之外的常规
resource
路由。 您可能希望将其保留在路径文件的低端/末端,因此其他更具体的路由优先。 编辑 :这个路由基本上是j_mcnally建议的第一个路由方法。 - 一个slug的所有逻辑,就像是一个有效的slug,都保留在这个模型中。 关注点的良好分离而非污染表示用户模型。 特别是如果slu children规则对于每个人来说都是一样的。
关于控制器的工作方式,我会选择Kyle所说的并关闭sluggable_type
字段来查找要渲染的视图。