【问题标题】:How to redirect from /:id to /:friendly_id如何从 /:id 重定向到 /:friendly_id
【发布时间】:2014-02-16 23:35:53
【问题描述】:

当有人尝试使用旧的/:id URL 而不是首选的/:friendly_id 链接浏览页面时,是否可以强制执行 301 重定向?

Apparently such redirections help to tell Google that you have updated the link.. 所以它停止显示旧的非友好链接。

【问题讨论】:

  • 简单的答案是做你所期望的:查找友好的 id 并返回重定向。
  • 在你的控制器中,只需做一个redirect_to,将你的新路由作为参数传递。

标签: ruby-on-rails


【解决方案1】:

使用最新版本的friendly_id(撰写此答案时为 5.0.3)和 Rails 4,我在控制器中执行此操作:

class ItemsController < ApplicationController
  before_action :set_item, only: [:show, :edit, :update, :destroy]

  ...

  private

  def set_item
    @item = Item.friendly.find(params[:id])
    redirect_to action: action_name, id: @item.friendly_id, status: 301 unless @item.friendly_id == params[:id]
  end
end

这是redirect_to 行的描述,逐段分解:

  • action: action_name 保留您正在连接的操作(可以根据现有的 before_action 显示、编辑、更新或销毁),因此如果您正在访问 /items/1/edit,您将被重定向到 @ 987654327@
  • id: @item.friendly_id 确保您被重定向到的 URL 是漂亮的 URL
  • status: 301 将重定向设置为 301 状态,用于 SEO
  • unless @item.friendly_id == params[:id] 确保我们不会重定向通过其漂亮 URL 访问 @item 的人

【讨论】:

  • 此重定向将清除使用原始 URL 提交的所有参数。例如,/items/4?filter=new 将变为 /items/item-slug-for-item-4,删除 filter 参数。要保留参数,请使用redirect_to request.params.merge(id: @event.friendly_id), status: 301 unless @item.friendly_id == params[:id]
【解决方案2】:

刚刚在路由文件中定义了重定向

get '/:old_id', to: redirect {|params, req| "/#{X.find(params[:old_id]).friendly_id}" }

【讨论】:

  • 另一种选择:get "/url_before" => redirect("/url_after")
【解决方案3】:

虽然 James Chevalier 的回答是正确的,但您可以将此方法提取到 ApplicationController 以便与任何使用 FriendlyId 的模型一起使用:

def redirect_resource_if_not_latest_friendly_id(resource)
  # This informs search engines with a 301 Moved Permanently status code that
  # the show should now be accessed at the new slug. Otherwise FriendlyId
  # would make the show accessible at all previous slugs.
  if resource.friendly_id != params[:id]
    redirect_to resource, status: 301
  end
end

如您所见,也没有必要将特定的 action 密钥传递给 redirect_to。将 Rails 模型传递给 redirect_to 将自动尝试访问相关集合资源路由上的 show 操作(假设它是这样设置的)。这也意味着没有必要传递 id 键,因为 FriendlyId 总是返回模型的 #to_param 中的最新 slug。

我不是unless 的忠实粉丝(混淆语义)我倾向于回避它,但这更多是我个人的偏好。

【讨论】:

    【解决方案4】:

    路线

    我不认为你的路线是这里的问题

    问题在于路由的后端处理(即是否使用friendly_id)。 Google 将看到的是:

    domain.com/users/45 
    domain.com/users/your_user
    

    如果这两条路线都有效,Google 会很高兴。我认为您是在暗示如果您将路线更改为仅处理 your_user,您需要能够让 Google 欣赏重定向


    重定向

    考虑到您可以在后端同时处理idslug(如果您愿意,我们有这方面的代码),我将使用ActionDispatch::Routing::Redirection 类处理重定向:

      #config/routes.rb
      begin  
        User.all.each do |u|
            begin
              get "#{u.id}" => redirect("#{u.slug}")
            rescue
            end
          end
      rescue
      end
    

    【讨论】:

    • 谢谢里奇。基本上,我希望 Google 忘记旧的 /:id 样式链接,因为这些链接对其页面排名系统的价值似乎较低。此外,结果中突出显示的 URL 看起来也不那么甜美。你认为我这样做是对的吗?
    • 语法错误,意外的 tSTRING_BEG,期待 keyword_do 或 '{' 或 '(' (SyntaxError) get "#{s.id}" => redirect "#{s.slug}"
    • 应该是u.idu.slug抱歉
    • 实际上我用 "#{u.id}" => redirect("#{u.slug}") 停止了错误,但重定向似乎没有发生。
    • 也许题外话了,但为了记录,如果给定的“页面”只有一个 URL,Google 会更高兴。如果有更多,他们会认为这是重复的内容,在极端情况下会损害您网站的排名。 support.google.com/webmasters/answer/66359?hl=en
    【解决方案5】:

    是的,有可能,您需要在 config/routes.rb 上定义两条路线

    get 'path/:id' => 'controller#action'
    get 'path/:friendly_id' => 'controller#action_2'
    

    那么您需要在旧的action 方法中提供一个

    return redirect_to controller_action_2_path(friendly_id: friendly_id),
                       status: :moved_permanently
    

    这将生成一个301 响应代码。这最终将使机器人开始接触您的新模式,而不会丢失您的任何流量或索引 (SEO)。

    【讨论】:

      猜你喜欢
      • 2021-04-25
      • 2019-01-26
      • 1970-01-01
      • 2018-09-01
      • 2017-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多