在 Rails 5 资源的显示操作中创建自定义 URL

Creating a custom URL in Rails 5 Resource's show action

鉴于资源事件,我希望 /events/1 在输入时导航到 URL 栏中的 /events/1/column_name。列名是事件数据库迁移中的 t.string :name。此 column_name 需要在重定向前调用 parameterize。关于如何完成这项工作有什么想法吗?

示例:

如果您在加载后导航到 https://whosebug.com/users/4180797 the URL will automatically become https://whosebug.com/users/4180797/james-lowrey。适用于 4180797/any-other-txt-here。所以 "James Lowrey" 将是 name 列,在调用 parameterize 后它将变为 james-lowrey

好吧,这真的很难弄清楚,甚至不知道我以前可以访问很多这些变量。

首先编辑您的 config/routes.rb 以接受 id/other_stuff

Rails.application.routes.draw do
  resources :events
  get "/events/:id/*other" => "events#show" #if any txt is trailing id, also send this route to events#show
end

如果 URL 不正确,下一步修改 event_controller.show 以重定向。

  def show
    #redirect if :name is not seen in the URL
    if request.format.html? 
      name_param = @event.name.parameterize
      url = request.original_url
      id_end_indx = url.index(@event.id.to_s) + (@event.id.to_s).length + 1 #+1 for '/' character
      ##all URL txt after id does not match name.parameterize
      if url[id_end_indx..-1] != @event.name.parameterize
        redirect_to "/events/#{@event.id}/#{name_param}"
      end
    end
  end

这将导致与问题中 Stack Overflow 示例完全相同的行为。

另一种选择是将 pushState 与 javascript/jquery 结合使用,例如:

首先在show.html.erb

中添加如下script
<script>
  $(document).ready(function() {
    history.pushState(null, null, "/events/<%= @event.id %>/<%= @event.name.parameterize %>");
  });
</script>

这将改变每次加载时的 url,无论 /:id 之后发生什么。

其次,修改路由以接受 /:id 之后的任何内容(并忽略它):

Rails.application.routes.draw do
  #...
  get "/events/:id/*other" => "events#show"
end

如果 /:id 之后的任何文本不匹配,此选项还有避免重定向的额外好处,它将只获取 id 并将其后的任何其他文本替换为 @event.name.parameterize在 url(没有任何重新加载)。