LoginSignup
11
20

More than 3 years have passed since last update.

[Rails]セレクトボックスで動的なグループ招待機能を作る

Last updated at Posted at 2019-05-13

やりたい事

Railsでアプリを作っているのですが、グループへの招待機能ってどう実装すれば良いんだ?と思い、考えてみました。

想定している仕様ですが、ユーザーは予めいくつかのグループを作成しており、ユーザーリストを見ながら「コイツいいじゃん!」って思ったユーザーを招待出来るようにします。
「どのユーザーをどのグループに招待するか」という組み合わせを取得する必要があります。

また、UIについてですが、ユーザー一覧に自分で作成したグループが表示されるセレクトボックスを設置し、ワンクリックで招待出来るようにしたいです。
送信ボタン等を押させたくないのでjavascriptでセレクトボックスの要素を取得して、get送信させる工夫が必要ですね。

準備

まずは、rails newしてアプリを作成して下さい。

rails new add_user --skip-bundle

jQuery追加

今回は、jqueryを使用します。
Gemfile.rbにjqueryを追加します。


gem 'jquery-rails'

# bundle installも忘れずに!
bundle install

app/assets/javascripts/application.jsに下記を追加してjqueryを読み込む設定をします。

//= require jquery

ちなみにES6を勉強中なのでES6で書きたかったのですが、ネット上の資料が豊富なのでjqueryに頼ってしまいました・・・

Modelの作成

rails g model user name:string introduction:text
rails g model group name:string introduction:text admin_user_id:integer
rails g model add_user_to_group user_id:integer group_id:integer activation:boolean

booleanにdefault: falseとnull: falseを追加。

class CreateAddUserToGroups < ActiveRecord::Migration[5.2]
  def change
    create_table :add_user_to_groups do |t|
      t.integer :user_id
      t.integer :group_id
      t.boolean :activation, default: false, null: false

      t.timestamps
    end
  end
end

マイグレーションしましょう。

rake db:migrate

テストデータ追加

今回の説明では、ユーザー1が「フットサルサークル」、「写真部」、「ボードゲーム愛好会」というグループを作り、他のユーザーを招待するというケースを想定して説明します。
作成したモデルにテストデータを追加しましょう。

# rail consoleを開く
rails console

# User作成

User.create(name: 'ユーザー1', introduction: 'グループを作りました!!')
User.create(name: 'ユーザー2', introduction: 'フットサルが趣味です')
User.create(name: 'ユーザー3', introduction: '写真が好きです')
User.create(name: 'ユーザー4', introduction: 'ボドゲマニアです')

# Group作成
# admin_user_idはグループの作成者user_id。ユーザー1が下記の3つのグループを作った事にします。

Group.create(name: 'フットサルサークル', introduction: 'みんなでフットサルしましょう', admin_user_id: 1)
Group.create(name: '写真部', introduction: '写真を撮りに行きましょう', admin_user_id: 1)
Group.create(name: 'ボードゲーム愛好会', introduction: 'ボードゲームしましょう', admin_user_id: 1)

admin_user_id: 1となっていますが、実際にはグループ作成時にカレントユーザーのidを入れます。
テストなので、ユーザー1が作ったグループという事にします。

コントローラー作成

ユーザーのリストとグループへの招待機能を作ります。
下記を実行してコントローラーを作って下さい。

rails g controller Users index add_user_to_group

routes.rbも自動で下記のようになるはずなので、確認。

Rails.application.routes.draw do
  get 'users/index'
  get 'users/add_user_to_group'
end

コーディング作業

ユーザー1が自分のグループに他のユーザーを招待するというケースを前提に説明します。

まずapp/controllers/users_controller.rbのindexに@users@groupを追加して下さい。
Groupは実際にはカレントユーザーが作成したグループを取得して実装します。
ユーザーの一覧から特定のユーザーを選び、自分が作成したグループに招待するためです。

class UsersController < ApplicationController
  def index
    @users = User.all
    # テストなのでadmin_user_idに1を設定していますが、実際はcurrent_userのidを設定しましょう。
    @groups = Group.where(admin_user_id: 1)
  end

  def add_user_to_group
  end
end

app/views/users/index.html.erbを下記のようにする。
グループ招待のセレクトボックスは自分以外のユーザーに表示します。自分で自分を招待する仕様はおかしいので。
ここでもuser.idが1じゃない時としてますが、実際はカレントユーザーのidを入れて、ログインしているユーザーと照合しましょう。


<h1>Users#index</h1>
<p>Find me in app/views/users/index.html.erb</p>

<% @users.each do |user| %>
 <p><%= user.name %>:<%= user.introduction %></p>
  <!-- テストなので、user.idが1じゃない時にしてますが、実際はcurrent_userのidではない時に表示にしましょう -->
  <% if user.id != 1 %>
  <select class='group' id=<%= "#{user.id}" %>>
    <option value="0">グループへ招待</option>
    <% @groups.each do |group| %>
      <option value=<%= "#{group.id}" %>><%= "#{group.name}" %></option>
    <% end %>>
  </select>
  <% end %>
  <hr>
<% end %>

この時点でrails sしてlocalhost:3000/users/indexにアクセスすると下記の画面になるはずです。
ユーザー1がログインして、他のユーザーをグループへ招待するというテストケースです。
ユーザー1以外のユーザーには、ユーザー1が作ったグループのセレクトボックスが追加されています。

スクリーンショット 2019-05-14 6.37.45.png

グループへの招待機能

セレクトボックスで選択したユーザーのidとグループのidを動的にget送信します。送信した後にコントローラーでユーザーとグループの組み合わせを招待情報として保存します。

js記述とget送信

先程のviewにjavascriptを追加します。viewにjavascriptをベタ書きするのは、本当は良くないのですが、筆者の体力もそろそろ限界のため、一旦ここに書いて動作確認とQiitaへのアウトプットをさせて下さい!

<h1>Users#index</h1>
<p>Find me in app/views/users/index.html.erb</p>
# ここから
<script>
  $(function() {
    // groupクラスの変更を検知する
    $('.group').change(function() {
      $.ajax({
     // getしたいurl
        url: "/users/add_user_to_group",
        // 送信形式にget設定
        type: "GET",
     // パラメーターにuser_idとgroup_idを追加して、コントローラーへ渡す
        data: { user_id: $(this).attr('id'), group_id: $(this).has('option:selected').val() }
      });
     // グループへ招待したら、画面上からグループを消す。
        $(this).children('option:selected').remove();
    });
  });
</script>
# ここまで追加

<% @users.each do |user| %>
 <p><%= user.name %>:<%= user.introduction %></p>
  <!-- テストなので、user.idが1じゃない時にしてますが、実際はcurrent_userではない時に表示にしましょう -->
  <% if user.id != 1 %>
  <select class='group' id=<%= "#{user.id}" %>>
    <option value="0">グループへ招待</option>
    <% @groups.each do |group| %>
      <option value=<%= "#{group.id}" %>><%= "#{group.name}" %></option>
    <% end %>>
  </select>
  <% end %>
  <hr>
<% end %>

ユーザーとグループの組み合わせをDBに保存

パラメーターで、user_idgroup_idが渡ってきているので、add_user_to_groupにて招待データを登録します。
AddUserToGroupuser_idgroup_idを登録する事で、どのユーザーが、どのグループに招待されているかわかるはず!
あとは、招待されたユーザー側の機能で、activationカラムをtrueにしたら正式にグループ参加する仕様で良いかな。

class UsersController < ApplicationController
  def index
    @users = User.all
    # テストなのでadmin_user_idに1を設定していますが、実際はcurrent_userのidを設定しましょう。
    @groups = Group.where(admin_user_id: 1)
  end

  # 以下を追加
  def add_user_to_group
    AddUserToGroup.create(user_id: params[:user_id], group_id: params[:group_id])
  end
end

見辛いですけど、user_idgroup_idの組み合わせがちゃんと入ってますね!
スクリーンショット 2019-05-14 7.45.52.png

とりあえずここまで。

改善点

今回、jQuery使っちゃいましたが、本当はES6勉強してるので、ES6で書きたいです。
JavaScript(ES6)の基本文法まとめ
JavaScript(ES6)の関数、オブジェクト、クラスのまとめ

あと、jQueryに関してなんですが、過去資料がかなり豊富なのに最近の記事は少ない感じがしました。
ブームが去ったという事でしょうか。
実務でもjQueryよりReact、Vue.jsを使いそうなので、フレームワークで実装出来るようにしたいですね。

11
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
20