プログラミングを完全に理解したエンジニアのメモ

チラ裏レベルのことしか書いてないインターネットの藻屑

deviseで招待用リンクを生成する(メールを使わずに招待機能を実装)

したいこと

  • 招待用URLを発行できる
  • メールを使わずにユーザーを招待できる

端折ること

  • URLと発行したユーザーのリレーション
  • 招待されたユーザーがどのURLから登録されたか
  • URLの期限
  • クリック数

実装

model

$ rails g model initation

migrationファイルは

class CreateInvitations < ActiveRecord::Migration[5.1]
  def change
    create_table :invitations do |t|
      t.string :token
      t.timestamps
    end
  end
end

端折った機能作りたいならここでclick_countなりlimited_atなりを足す

controller

$ rails g controller users::invitations

routes.rb

namespace :users do
    resource :invitations, only: [:show, :update]
  end

を追加

invitations_controller.rb

class Users::InvitationsController < ApplicationController
  before_action :authenticate_user!

  def show
    if Invitation.count == 0
      Invitation.create!(token: SecureRandom.uuid.gsub!(/-/,''))
      @invitation_token_url =  "http://localhost:3000/users/sign_up?tk=" + Invitation.all.last.token.to_s
    else
      @invitation_token_url =  "http://localhost:3000/users/sign_up?tk=" + Invitation.all.last.token.to_s
    end
  end

  def update
    Invitation.create!(token: SecureRandom.uuid.gsub!(/-/,''))
    @invitation_token_url =  "http://localhost:3000/users/sign_up?tk=" + Invitation.all.last.token.to_s
    redirect_to users_invitations_path, notice: "URLを作成しました"
  end
end

(注意)

  • ここらへんheplerにまとめる。
  • URLはgem 'config'でベタ打ちにしない

views/invitations/show.html.slim

.container-fluid
  .container
    .row
      .col-sm-12
        h4 招待用URL作成
        = text_field_tag '#', @invitation_token_url, class: 'form-control'

        .margin-top-30
          = link_to 'URLを再作成する', users_invitations_path, { method: 'put', class: 'btn btn-primary' }

clipboardjs.com

これとか入れる

registrations_controller.rb

ここで一番はじめのユーザー以外の直リンクと不正なtoken or token無しをはじく

class Users::RegistrationsController < Devise::RegistrationsController
  before_action :check_sign_up_token, only: [:new]

  (略)

  protected

  # 新規登録にtoken無しでアクセスさせない
  def check_sign_up_token
    return redirect_to root_path if params[:tk].nil? || User.count == 0 || !Invitation.exists?(token: params[:tk])
  end
end

アクセスした時にtokenをcookieに保存して、createの時にチェックするようにした方がよい(?)