🐣

scopeとwhereメソッドを使って自分以外のユーザーを検索したい

2022/03/17に公開

やりたいこと

ユーザーを検索したときに、自分(ログインしているユーザー)は検索対象外にしたい

  1. ユーザー名「たなか」でログイン
  2. 「たなか」というキーワードで検索
  3. 検索結果には自分以外の「たなか」のみヒットする

背景と開発環境

開発中のアプリケーションにフォロー機能を実装しました。

フォローボタンは各ユーザーの詳細ページに置いています。そのため、他のユーザーをフォローするには、そのユーザーの詳細ページに移動する必要があります。

そこで、ユーザー名で検索して、フォローしたいユーザーを見つけます。
その検索結果に自分を表示する必要はないし、なんだか見た目も悪いですよね。

以下、参考までに開発環境です。
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 %>

現時点では自分以外のユーザーをすべて検索対象に入れましたが、相互フォロー状態のユーザーも検索対象から外すかどうか検討中です。もしその場合でも引数に追加してあげればすぐに実装できそうな気がします。

参考

https://pikawaka.com/rails/where
https://qiita.com/hapiblog2020/items/6c2cef49df5616da9ae3

Discussion