1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

オリジナルアプリにパートナー申請機能を実装する

Posted at

#概要

  • オリジナルアプリ作成にあたり、ユーザ(current_user)が他ユーザに対してパートナー申請をする画面をトップページ(toppages#index)に実装したい。
  • 申請手順は以下の通りとなる。
    1. 自分(ユーザA)がパートナー(ユーザB)に対して招待を送る。その際にユーザAは「秘密の言葉」を設定しておく。
    2. パートナーのトップページに「招待が届きました」というメッセージが届き、それを「承認」か「拒否」かを選択する。承認する場合にはユーザAが設定した「秘密の言葉」を入力する必要がある。
    3. 承認された場合はユーザAとユーザBはパートナーとなる。
  • ユーザと他ユーザがパートナーである事は中間テーブルrelationshipsに定義する。

#手順

パートナー申請フォーム作成

中間テーブルrelationshipsにて多対多の関係(ユーザと他ユーザがパートナーである状態)を表す。

  • 中間テーブルrelationshipsのカラム構成
id user_id partner_id status secret_words

form_withを用い、relationshipsテーブルにデータが登録されるようにする。
relationshipsのパーシャルでパートナー申請フォームを作成する。

relationships/_offer_form.html.erb
<div class="row">
    <div class="col-sm-6 offset-sm-3">
        <%= form_with(model: relationship, local: true) do |f| %>
            <div class="form-group">
                # relationshipテーブルに無いデータの入力の為、"f.~"ではなく"~_tag"を用いる
                # 初期値をテキストボックスに表示しておきたい場合、""内に値を入れる(今回は不要の為、ブランク)
                <%= label_tag :name, "パートナー申請先(ユーザ名)" %>
                <%= text_field_tag :name, "", class: "form-control" %>
            </div>
            <div class="form-group">
                <%= f.label :secret_words, "秘密の言葉" %>
                <%= f.text_field :secret_words, class: "form-control" %>
            </div>
            
            <%= hidden_field_tag :status, "承認待ち" %>
            
            <%= f.submit "招待する", class: "btn btn-primary btn-block" %>
        <% end %>
    </div>
</div>

パートナー申請画面作成

relationshipsのパーシャルで作成した申請フォームをrenderで読み込む。

views/toppages/index.html.erb

<div class="text-center">
    <h1>パートナー申請画面</h1>
</div>
# classを跨ぐ場合はインスタンス変数を用いるとclass間で依存関係が出来てしまうので、使用しないほうが良い
<%= render "relationships/offer_form", relationship: @relationship %>

toppages controllerの実装

relationshipsのパーシャルで申請フォームを作成した為、インスタンス変数もRelationshipsControllerで定義するものだと勘違いしやすいが、それは誤りである。仮に別クラスのパーシャルであったとしてもviewに表示されているインスタンス変数はそのアクションを定義しているcontrollerに紐づいている為、今回の場合はインスタンス変数(@relationship)はtoppages#indexで定義する。

controllers/toppages_controller.rb
class ToppagesController < ApplicationController
  def index
    if logged_in?
      # インスタンス変数を@relationshipとし、form_withのmodel引数に設定してあげることで
      # action先をRelationshipsController#createに暗に飛ばすことが出来る
      @relationship = current_user.relationships.build
    end
  end
end

(補足情報)

current_userとlogged_in?のメソッドはSessionsHelperにて定義している。

helpers/sessions_helper.rb
module SessionsHelper
    def current_user
        @current_user ||= User.find_by(id: session[:user_id])
    end
    
    def logged_in?
        !!current_user
    end
end

helperはviewでのみしか機能しないので、controllerで使用したい場合はmix-inをする。
今回、ToppagesControllerで使用したいが、他でも使用する可能性が高い為、全体に適用すべくApplicationControllerにmix-inしておく。

controllers/application_contoller.rb
class ApplicationController < ActionController::Base
    # SessionsHelperをmix-in
    include SessionsHelper

    private
    
    def require_user_logged_in
        unless logged_in?
            redirect_to login_url
        end
    end
end
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?