0

RailsアプリケーションでOmniAuth-identityを実行し、ユーザーを「ユーザー」モデルで保存しました。ユーザーにアクセスするには、次を指す必要があります。

0.0.0.0:3000/users/:id

しかし、facebook や twitter のように、ユーザーの一意の名前を入力するだけでそこに到達したかったのです。

0.0.0.0:3000/username

そこで、グローブ ルートを作成しました。

match "/*id" => "users#show"

渡されたパラメーターに応じて、ID ではなく名前で検索するようにユーザーコントローラーの show メソッドを変更しました。

def show
    if params[:id].is_a?(String)
      @user = User.find_by_name(params[:id])
    else
      @user = User.find(params[:id])
    end
    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @user }
    end
  end

ルーティングが機能します。

0.0.0.0:3000/username

ユーザー情報が正常に表示されます。しかし、ログアウトしたり、古いルートのようにユーザーを見つけたりすることはできません.. (コントローラーに追加した条件で String||Int.

これを行うと、次のようになります。

NoMethodError in Users#show

Showing /home/juanchi/Dropbox/GitHub/RSandBox/app/views/users/show.html.erb where line #5 raised:

undefined method `provider' for nil:NilClass
Extracted source (around line #5):

2: 
3: <p>
4:   <b>Provider:</b>
5:   <%= @user.provider %>
6: </p>
7: 
8: <p>
Rails.root: /home/juanchi/Dropbox/GitHub/RSandBox

Application Trace | Framework Trace | Full Trace
app/views/users/show.html.erb:5:in `_app_views_users_show_html_erb___448583227_80374500'
app/controllers/users_controller.rb:22:in `show'
Request

Parameters:

{"id"=>"logout"}
Show session dump

Show env dump

Response

Headers:

None

ユーザー コントローラーの show メソッドでの情報の取得に失敗します。しかし、新しいルートを使用するとうまくいきます...では、何が欠けているのでしょうか?

新しいルーティング ルールと古いルーティング ルールを同時にサポートするにはどうすればよいですか?

そして、そのルートはユーザーのログアウト方法とどのような関係があるのでしょうか?

ログアウトすると、sessions#detroy メソッドが呼び出されます。

def destroy
    session[:user_id] = nil
    redirect_to root_url, :notice => "Goodbye!"
  end
4

1 に答える 1

1

アイデアが得られたかどうかはわかりませんが、グロブ化されたルートを使用する必要はないと思います。

次のようなものを使用できます。

get "users/:id" => "users#show"
get ":username" => "users#show"

そして、アクションでパラメータの存在を確認できます:

def show
  if params[:id].present?
    @user = User.find(params[:id])
  elsif params[:username].present?
    @user = User.find_by_name(params[:username])
  end
end

コードにあるようにパラメーターのタイプをチェックすることは、常に String (または nil の場合は NilClass) であるため意味がありません。

また、重要な点が 1 つあります。ルートは順序付けされているためget ":username" ...、/logout、/login などの標準アクションとの競合を防ぐために、ルーティング テーブルの最後に自分の場所を配置する必要があります。

実際、これらの競合を完全に排除するのは簡単ではありません。「ログアウト」という名前を選択したユーザーがいるとします。したがって、ユーザーのそのような名前を防止する別のロジックを追加する必要があります。

更新:グロビングが不要であると考える理由を説明するのを忘れていました。1 つのルールで「foo/bar」、「something/nice/in/rails」などをキャッチするには、グロビングが必要です。match "*xxx"

于 2012-09-11T22:11:17.543 に答える