5

私が取り組んでいるRailsアプリには、さまざまなモデルがあります。多くのサイトがアプリ全体のスラッグ ルーティング アプローチを使用しているのを見てきました。これはどういう意味ですか?

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 とアプリ内で読みやすいスラッグを作成することは知っていますが、さまざまなオブジェクトに対してルートレベルのスラッグを作成する方法については知りません。これは、Facebook の Graph API に似ていると考えることができます。さまざまなオブジェクト タイプがありますが、それらはすべてhttps://graph.facebook.com/object-idに存在します。

どんな洞察も大歓迎です!

4

3 に答える 3

10

freindly_id でこれを行う方法があるかもしれませんが、フレンドリー ID の問題は、物事がモデルによってスコープされていることだと思います。

本当にサイト全体のスラッグが必要な場合は、すべてのモデルとのポリモーフィックな関係を持つスラッグ テーブルを作成します。

Sluggable_type と sluggable_id、そして完全なパーマリンク/スラッグを含むスラッグ フィールド。

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

これで、すべてのルートをキャッチするワイルドカードを実行するか、実行時にすべてのスラッグのルートを作成し、このスラッガブルな制御下にあるモデルが更新されたときにルートを強制的に更新することができます。

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

ルーティングに2番目のアプローチを使用する場合は、必ず呼び出してください

YOUR_APP_NAME::Application.reload_routes!

遅延したレコードを編集してルーティング テーブルを更新した後。

私たちも同様の問題を抱えており、このアプローチをジェム化することを試みるかもしれません。

于 2013-03-13T19:04:21.090 に答える
2

少なくとも最初のパスとして、おそらく次のようにアプローチします。

  • 関連する各モデルのスラッグを生成するには、 Friendly_id などを使用します
  • のキャッチオールルートを接続し/([-_a-zA-Z0-9]+)、次のようなものに向けますEntitiesController#show
  • /developersを指すためのより優先度の高いルートを接続しますUsers#index
  • 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"

また、検索結果をアクセス頻度の高い順に並べます (最初に推測し、後でデータを使用して順序を微調整します)。

最後に、おそらく明らかですが、リクエストごとに複数の検索を行うことが多いため、各テーブルのスラッグ列にインデックスを付けていることを確認してください。

FWIW これにもアプローチするより良い方法を知りたいです。これは、私が最初に問題に取り組む方法です。

于 2013-03-13T18:09:52.073 に答える
0

私の最初の反応は、新しい Slug モデルを作成することです。このモデルには多態性がありbelongs_toます:

belongs_to :sluggable, :polymorphic => true

少なくとも、このテーブルには次のものが含まれます。

  • value- または、これよりも適切な名前。スラッグ自体の値。
  • sluggable_typeおよびsluggable_id- ポリモーフィック外部キー。

あなたの会社、ユーザーなどのモデルのモデルにはスラッグがあります:

has_one :slug

これにより、すぐにいくつかの利点が得られます。

  • スラグ値に一意の制約を簡単に作成できるようになりました。slug がすべての異なる sluggable モデルのプロパティとして保持されている場合、一意の制約は他のすべての sluggable テーブルの一意性をチェックする必要があります。悪い時間を作ります。
  • resourceルート レベルの名前空間から離れた通常のルートを使用できるため、ルーティングは非常に単純です。他のより具体的なルートが優先されるように、ルートファイルの最後/最後にそれを維持したいでしょう。編集: このルーティングは、基本的に j_mcnally が提案する最初のルーティング方法です。
  • 有効なスラッグを作成するものなど、スラッグのすべてのロジックは、この 1 つのモデルに保持されます。ユーザーモデルを汚染するのではなく、懸念事項を適切に分離します。特にスラッグルールがここにいる全員にとって同じである場合.

コントローラーがどのように機能するかという点では、Kyle が言ったことに従い、sluggable_typeフィールドをキーオフして、レンダリングするビューを見つけます。

于 2013-03-13T19:13:57.413 に答える