[Rails, jQuery]インクリメンタルサーチ+αを実装
[Rails, jQuery]インクリメンタルサーチ+αを実装:
現在プログラミングスクールにて学習中です。
カリキュラムでchatアプリの開発をしていて、インクリメンタルサーチをajaxを使用し、実装するところでハマった部分があったので記録に残そうと思います。
今回作成しているchatアプリでは、groupsテーブル、usersテーブル、messagesテーブルがあり、groupsとusersは多対多の関係です。
中間テーブルはgroup_usersとしていてgroup_idとuser_idで紐づいています。
インクリメンタルサーチはgroupの新規作成とgroup編集で使用します。
メンバー検索欄に文字を入力するとuserの候補がでてくる仕様です。
Googleなどで検索欄に文字を打つと色々候補が出て来ると思いますが、それのことです。
インクリメンタルサーチの実装はできているが、group新規作成でcurrent_userを検索候補で非表示にしたい方。
group編集でcurrent_user含め既にgroupに所属しているuserを検索候補から非表示にしたい方。
group新規作成の際にcurrent_userを検索で表示しないようにします。
最初からグループに参加していてほしいユーザーになるので、検索する時にcurrent_userを参加させますか?と出てきたら変ですよね。
それを防ぐためにcontrollerで処理をしてあげます。
LIKE句でUserモデルから曖昧検索をします。
name LIKE(?)の?部分にparams[:keyword]が入ります。
これで曖昧検索はOKです。
where文はandやorで条件を繋げることができるので、and (id != ?)と書き、#{current_user}を?に入れてあげます。
これでcontrollerの記述は終わりです。
上記のようにしておけばグループ新規作成で初めからログイン中のメンバーが表示されるようになります。
このようになればOKです。
続いてグループ編集です。
下の画像のようにグループに参加しているメンバーは全員表示されていてチャットメンバーを追加部分に出てこないようにします。
まず①では、チャットメンバーのところに既にグループ参加済みのユーザー名を表示させます。
グループのメンバーなのでgroups_controllerに記述します。
groupに所属しているユーザーをインスタンス変数にいれます。
次はhtmlを修正します。
groupメンバーを1人ずつ表示しなければならないのでeach文で表示してあげます。
このままだとmembersなんて無いよとエラーがでるのでrenderしているhtmlも変更します。
これでチャットメンバーの部分はOKだと思います。
次はインクリメンタルサーチの部分ですね。
考え方としては
・編集するgroupのidをhtmlからjsに送れるようする。
・jsでgroupのidを取得しajaxでcontrollerに送れるようにする。
・controllerで既に所属しているユーザーを非表示にできるように省く。
新規作成のcurrent_userを省く時とほぼ同じなのですが、同じcontroller,jsなどを使用するので非常に難しかったです。
まずはhtml
文字を入力する検索欄にてhidden_fieldを使用しgroup.idを送るようにしてあげます。
class名はjsで取得できればいいので好きなのにしてください。
3行目の処理でgroup.idをgroup_idという変数に代入し、7行目でgroupIdというparamsでcontrollerに送信します。
groupIdじゃなくてgroup_idでもいいと思います。
2行追加で記述しgroupに所属しているユーザーを取得できました。
これで編集画面のインクリメンタルサーチも完成!なんですが、このままだとグループ新規作成でエラーが出るようになってしまいます。
新規作成でgroup.idは存在していないので、何だそれは?というエラーです。
そこでifを使って条件分岐します。
これで完成です。
一応動作は思っていた通りになりました。
コードは汚いですが、、、、
where.notとwhereの部分とか・・・
あとindexアクションに色々書いているのでmodelに書いたほうがいいのかなーとも思ったりしてます。
users_controllerでGroupモデルからデータを取得しているのでそれも違和感ですね。
そもそもajaxとかjsの書き方がよくわかっていない中での実装だったので苦戦しました。
特に編集画面のところはどうやってやればいいんだとかなり悩んで苦しい思いをした箇所です。
ただ、ajaxを学習してJS面白いなーと思ったので引き続き学んで書いていきたいと思います!
もちろんRuby、Railsも!
この記事が少しでも誰かの役に立てば良いなと思います!
はじめに
現在プログラミングスクールにて学習中です。カリキュラムでchatアプリの開発をしていて、インクリメンタルサーチをajaxを使用し、実装するところでハマった部分があったので記録に残そうと思います。
chatアプリ概要
今回作成しているchatアプリでは、groupsテーブル、usersテーブル、messagesテーブルがあり、groupsとusersは多対多の関係です。中間テーブルはgroup_usersとしていてgroup_idとuser_idで紐づいています。
インクリメンタルサーチはgroupの新規作成とgroup編集で使用します。
メンバー検索欄に文字を入力するとuserの候補がでてくる仕様です。
そもそもインクリメンタルサーチとは
Googleなどで検索欄に文字を打つと色々候補が出て来ると思いますが、それのことです。
対象読者
インクリメンタルサーチの実装はできているが、group新規作成でcurrent_userを検索候補で非表示にしたい方。group編集でcurrent_user含め既にgroupに所属しているuserを検索候補から非表示にしたい方。
group新規作成について
group新規作成の際にcurrent_userを検索で表示しないようにします。最初からグループに参加していてほしいユーザーになるので、検索する時にcurrent_userを参加させますか?と出てきたら変ですよね。
それを防ぐためにcontrollerで処理をしてあげます。
users_controller.rb
def index @users = User.where('(name LIKE(?) and (id != ?)', "%#{params[:keyword}%", "#{current_user.id}") respond_to do |format| format.json end end
name LIKE(?)の?部分にparams[:keyword]が入ります。
これで曖昧検索はOKです。
where文はandやorで条件を繋げることができるので、and (id != ?)と書き、#{current_user}を?に入れてあげます。
これでcontrollerの記述は終わりです。
_form.html.haml
#chat-group-users #chat-group-user-22.chat-group-user.clearfix %input{ name: "group[user_ids][]", type: "hidden", value: "#{current_user.id}" } %p.chat-group-user__name = current_user.name
このようになればOKです。
group編集について ①
続いてグループ編集です。下の画像のようにグループに参加しているメンバーは全員表示されていてチャットメンバーを追加部分に出てこないようにします。
まず①では、チャットメンバーのところに既にグループ参加済みのユーザー名を表示させます。
グループのメンバーなのでgroups_controllerに記述します。
groups_controller.rb
#追加部分は@members def new @group = Group.new @group.users << current_user @members = @group.users end #省略 #追加部分は@members def edit @group = Group.find(params[:id]) @members = @group.users end
次はhtmlを修正します。
_form.html.haml
# each文追加 - members.each do |member| #chat-group-users #chat-group-user-22.chat-group-user.clearfix # inputのvalueとcurrent_user.nameだった部分を変更 %input{ name: "group[user_ids][]", type: "hidden", value: "#{member.id}" } %p.chat-group-user__name = member.name
このままだとmembersなんて無いよとエラーがでるのでrenderしているhtmlも変更します。
edit.html.haml
#修正前 = render partial: 'form', locals: { group: @group } #修正後 = render partial: 'form', locals: { group: @group, members: @members }
new.html.haml
#修正前 = render partial: 'form', locals: { group: @group } #修正後 = render partial: 'form', locals: { group: @group, members: @members }
グループ編集について②
次はインクリメンタルサーチの部分ですね。考え方としては
・編集するgroupのidをhtmlからjsに送れるようする。
・jsでgroupのidを取得しajaxでcontrollerに送れるようにする。
・controllerで既に所属しているユーザーを非表示にできるように省く。
新規作成のcurrent_userを省く時とほぼ同じなのですが、同じcontroller,jsなどを使用するので非常に難しかったです。
まずはhtml
_form.html.haml
= f.text_field :name, class: "chat__group_name chat-group-form__input", placeholder: "グループ名を入力してください" = f.hidden_field :id, class: "chat__group_id", value: group.id
class名はjsで取得できればいいので好きなのにしてください。
user.js
$("#user-search-field").on("keyup", function() { var input = $("#user-search-field").val(); var group_id = $('.chat__group_id').val(); $.ajax({ type: 'GET', url: '/users', data: { keyword: input, groupId: group_id }, dataType: 'json' })
groupIdじゃなくてgroup_idでもいいと思います。
users_controller.rb
# findでgroupIdに一致するgroupのデータを代入します。 @group = Group.find(params[:groupId]) # groupに所属しているuserのidを配列で取得 @ids = @group.users.ids def index @users = User.where('(name LIKE(?) and (id != ?)', "%#{params[:keyword}%", "#{current_user.id}") respond_to do |format| format.json end end
users_controller.rb
# 追加記述前 @users = User.where('(name LIKE(?) and (id != ?)', "%#{params[:keyword}%", "#{current_user.id}") # where.notを追加記述します。 @users = User.where.not(id: @ids).where('(name LIKE(?)) and (id != ?)', "%#{params[:keyword]}%", "#{current_user.id}")
新規作成でgroup.idは存在していないので、何だそれは?というエラーです。
そこでifを使って条件分岐します。
users_controller.rb
def index # そもそもgroupのidがあるのか?という条件分岐です。 if params[:groupId].present? #group.idがあればの処理 @group = Group.find(params[:groupId]) @ids = @group.users.ids @users = User.where.not(id: @ids).where('(name LIKE(?)) and (id != ?)', "%#{params[:keyword]}%", "#{current_user.id}") else # group.idがなければcurrent_userだけ省く @users = User.where('(name LIKE(?)) and (id != ?)', "%#{params[:keyword]}%", "#{current_user.id}") end respond_to do |format| format.json end end
最後に
一応動作は思っていた通りになりました。コードは汚いですが、、、、
where.notとwhereの部分とか・・・
あとindexアクションに色々書いているのでmodelに書いたほうがいいのかなーとも思ったりしてます。
users_controllerでGroupモデルからデータを取得しているのでそれも違和感ですね。
そもそもajaxとかjsの書き方がよくわかっていない中での実装だったので苦戦しました。
特に編集画面のところはどうやってやればいいんだとかなり悩んで苦しい思いをした箇所です。
ただ、ajaxを学習してJS面白いなーと思ったので引き続き学んで書いていきたいと思います!
もちろんRuby、Railsも!
この記事が少しでも誰かの役に立てば良いなと思います!
コメント
コメントを投稿