🐣
scopeとwhereメソッドを使って自分以外のユーザーを検索したい
やりたいこと
ユーザーを検索したときに、自分(ログインしているユーザー)は検索対象外にしたい
- ユーザー名「たなか」でログイン
- 「たなか」というキーワードで検索
- 検索結果には自分以外の「たなか」のみヒットする
背景と開発環境
開発中のアプリケーションにフォロー機能を実装しました。
フォローボタンは各ユーザーの詳細ページに置いています。そのため、他のユーザーをフォローするには、そのユーザーの詳細ページに移動する必要があります。
そこで、ユーザー名で検索して、フォローしたいユーザーを見つけます。
その検索結果に自分を表示する必要はないし、なんだか見た目も悪いですよね。
以下、参考までに開発環境です。
Ruby 3.3.3
Ruby on Rails 7.0.2
トライそしてエラー
Userモデルに、scopeとwhereメソッドで検索対象のユーザを限定したうえで、
Usersコントローラーでsearchメソッドを作成してみます。
・・・あれ??エラーが・・・
ArgumentError in UsersController#search
wrong number of arguments (given 0, expected 1)
渡す引数がないやんけ!と怒られました
エラー原因
コントローラー側で引数の指定(どのユーザーをスコープから外すか)をしていなかったのが原因でした。
修正したらうまく動いてくれました!
修正前
def search
@search_friends = User.others.search(params[:keyword])
end
修正後
def search
@search_friends = User.others(current_user).search(params[:keyword])
end
最終的なコード
models/user.rb
class User < ApplicationRecord
#省略
# ユーザー検索
def self.search(search)
User.where('user_name LIKE(?)', "%#{search}%") if search != ''
end
# ユーザー検索範囲から対象ユーザーを除く
scope :others, ->(user) { where.not(id: user.id) }
end
controllers/users_controller.rb
class UsersController < ApplicationController
#省略
def search
@search_friends = User.others(current_user).search(params[:keyword])
end
end
routes.rb
Rails.application.routes.draw do
#省略
resources :users, only: [:show, :index] do
collection do
get 'search'
end
end
end
views/users/search.html.erb
<%= form_with(url: search_users_path, local: true, method: :get) do |form| %>
<%= form.text_field :keyword, placeholder: "ユーザーを探す" %>
<% end %>
現時点では自分以外のユーザーをすべて検索対象に入れましたが、相互フォロー状態のユーザーも検索対象から外すかどうか検討中です。もしその場合でも引数に追加してあげればすぐに実装できそうな気がします。
参考
Discussion