古いURLをリダイレクトするRails

ここでは、ページを新しいURLに移動するのにどのように苦労したかを説明します。

この投稿は、Ruby On Railsの初心者を対象としています。



最初は、独自のRuby on Railsプロジェクトがあり、その中のurl構造は次のようになります。/ locale / group / product

例:/ ru / bar-code-scanners / datalogic-magelan-1100i



グループ製品はパーマリンク-IDの代わりにDBで検索が実行される行。



問題は、サイトにコンテンツを追加するユーザーがパーマリンクエラーを起こすことがあるということです。

次に例を示します。/ ru / bar-code-scanners / datalogic-magelan-1100i

間違いは、マゼランが2つのll-mage ll anと書かれていることです。

しかし、製品は比較的長い時間前に追加され、ページはすでに検索エンジンによってインデックス化されているため、タスクはパーマリンクを修正し、新しいURLへのリダイレクトを構成することです。



もちろん、この問題はnginxまたはapacheレベルで解決できます。 ただし、通常は管理者のみがWebサーバーにアクセスでき、さらにリダイレクトの編集もいくつかのロケールではかなり日常的なタスクです。

したがって、私はこのビジネスを自動化することにしました。このため、ポリモーフィック接続を持つ単純なリダイレクトモデルを作成しました。つまり、製品とグループの両方に属することができます。



移行ファイル20131113223332_create_redirections.rb

class CreateRedirections < ActiveRecord::Migration def change create_table :redirections do |t| t.references :redirectable, polymorphic: true t.string :permalink t.timestamps end end end
      
      







次に、リダイレクトモデル自体を示します。

 class Redirection < ActiveRecord::Base attr_accessible :permalink belongs_to :redirectable, polymorphic: true def self.product(permalink) redirection = Redirection.where(permalink: permalink, redirectable_type: "Product").first redirection.redirectable if not redirection.nil? end def self.group(permalink) redirection = Redirection.where(permalink: permalink, redirectable_type: "Group").first redirection.redirectable if not redirection.nil? end end
      
      







これで、グループと製品のアドレス指定を構成する必要がある各モデルを微調整することができます。

リダイレクションモデルにリンクを追加します。

  has_many :redirections, as: :redirectable, :dependent=>:destroy
      
      







ここで、permalink属性に変更の追跡を実装し、必要に応じてリダイレクトレコードを作成する必要があります。

幸いなことに、パーマリンクを持つすべてのモデルは、AbstractContent中間クラスの1つから継承されます。 そのため、DRYの原則に違反することなく、このクラスでのみパーマリンクを変更するトラッキングコードを追加するだけで十分です。



それが私がRailsを愛している理由です-実際の追跡は初歩的なものであることが判明しました。 Railsは非常に便利な_changedメソッドでモデルとその属性を拡張しますか? と_was。



必要なことは、コールバックafter_saveを追加するだけです。コールバックは、変更を追跡し、必要に応じて、リダイレクトモデルの新しいレコードを作成します



 class AbstractContent < ActiveRecord::Base self.abstract_class = true after_save :check_permalink_changes def check_permalink_changes if self.permalink_changed? if self.permalink_was self.redirections.create!(permalink: self.permalink_was) end end end end
      
      







コントローラで転送自体を設定するためだけに残ります



 class GroupsController < ApplicationController def show @group = Group.find_by_permalink(params[:id]) if @group.nil? @group = Redirection.group(params[:id]) || not_found redirect_to group_path(@group), status: 301 end end end
      
      







そして、ステータス301を追加することを忘れないでください-永久に移動しました。 デフォルトでは、302が返されます-一時的に移動されます。



2番目のコントローラーのコードを引用することは似ているため、意味がないと思います。

また、プロジェクトの実際のコードでは、find_by_permalinkがキャッシュを介して検索され、find_in_cacheがここから削除されて、例が簡略化されています。



便利なエラー呼び出し404のために、例外をスローするApplicationControllerにnot_foundメソッドが追加されました。



  def not_found raise ActionController::RoutingError.new('Not Found') end
      
      







ところで、production.logを調べたくないが、必要な構造/グループ/製品のURLリクエストごとにすべてのエラーを表示したい場合。 その後、すべてのnot_found呼び出しのログを別のファイルに追加すると便利です。



PSまあ、あなたはまだRedirectionsControllerを追加して、すべてのリダイレクトを管理および追跡できます。



All Articles