前提・実現したいこと
ポートフォリオの作成でActionTextを使用したブログ投稿アプリを作成しています。
フォロー機能を付けたくてRailsでフォロー機能を作る方法という記事を参考に実装を進めています。
発生している問題・エラーメッセージ
ブログの詳細ページでフォローができるようにしたいのですが、フォローをするボタンが表示されません。
テラテイルの中でも過去に同じ記事を参考にしていた方の質問も参考にしてエラーの解決を試みましたが、うまくいきませんでした。
該当のソースコード
relationshipsテーブル
class CreateRelationships < ActiveRecord::Migration[6.0] def change create_table :relationships do |t| t.references :user, foreign_key: true t.references :follow, foreign_key: { to_table: :users } t.timestamps t.index [:user_id, :follow_id], unique: true end end end
relationshipsモデルのアソシエーション
class Relationship < ApplicationRecord belongs_to :user belongs_to :follow, class_name: 'User' validates :user_id, presence: true validates :follow_id, presence: true end
userモデルのアソシエーション
class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable,:recoverable, :rememberable has_one_attached :image has_many :posts, dependent: :destroy has_many :comments, dependent: :destroy has_many :likes, dependent: :destroy has_many :like_posts, through: :likes, source: :post has_many :relationships has_many :followings, through: :relationships, source: :follow has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id' has_many :followers, through: :reverse_of_relationships, source: :user validates :profile, length: { maximum: 200 } with_options presence: true do validates :nickname, presence: true, length: { maximum: 10 } EMAIL_REGEX = /@+/.freeze validates :email, uniqueness: { case_sensitive: true }, format: { with: EMAIL_REGEX, message: '@を使用してください' } PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[\d])[a-z\d]+\z/i.freeze validates :password, confirmation: true, length: { minimum: 6 }, format: { with: PASSWORD_REGEX, message: 'には英字と数字の両方を含めて設定してください' } end def follow(other_user) unless self == other_user self.relationships.find_or_create_by(follow_id: other_user.id) end end def unfollow(other_user) relationship = self.relationships.find_by(follow_id: other_user.id) if relationship relationship.destroy end end def following?(other_user) self.followings.include?(other_user) end end
relationshipsコントローラ
class RelationshipsController < ApplicationController before_action :set_user def create follwing = current_user.follow(@user) if following.seve flash[:success] = 'ユーザーをフォローしました' redirect_to @user else flash.now[:alert] = 'ユーザーのフォローに失敗しました' redirect_to @user end end def destroy following = current_user.unfollow(@user) if following.destroy flash[:success] = 'ユーザーのフォローを解除しました' redirect_to @user else flash.now[:alert] = 'ユーザーのフォロー解除に失敗しました' redirect_to @user end end private def set_user @user = User.find(params[:follow_id]) end end
postsコントローラー
class PostsController < ApplicationController before_action :set_post, only: [:show, :edit] before_action :move_to_index, except: [:index, :show, :search] def index @posts = Post.includes(:user).order("created_at DESC") @post = Post.includes(:user) end def show @comment = Comment.new @comments = @post.comments.includes(:user).order("created_at DESC") @user = User.find(params[:id]) end def new @post = Post.new end def edit end def create @post = Post.new(post_params) if @post.valid? @post.save redirect_to root_path else render :new end end def update @post = Post.find(params[:id]) if @post.update(post_params) redirect_to root_path else render :edit end end def destroy post = Post.find(params[:id]) if post.destroy redirect_to root_path else render :show end end def search @posts = Post.searchtext(params[:keyword]) end private def set_post @post = Post.find(params[:id]) end def post_params params.require(:post).permit(:title, :content, :image, :likes_count).merge(user_id: current_user.id) end def move_to_index unless user_signed_in? redirect_to action: :index end end end
フォローのボタン
app/views/relationships/_follow_button.html.erb
<% if user_signed_in? %> <% unless current_user == user %> <% if current_user.following?(user) %> <%= form_for(current_user.relationships.find_by(follow_id: user.id), html: { method: :delete }) do |f| %> <%= hidden_field_tag :follow_id, user.id %> <%= f.submit 'Unfollow', class: 'btn btn-danger btn-block' %> <% end %> <% else %> <%= form_for(current_user.relationships.build) do |f| %> <%= hidden_field_tag :follow_id, user.id %> <%= f.submit 'Follow', class: 'btn btn-primary btn-block' %> <% end %> <% end %> <% end %> <% end %>
ルーティング
Rails.application.routes.draw do devise_for :users, only: [:show] devise_for :users, controllers: { registrations: 'users/registrations' } root to: "posts#index" resources :posts do resources :comments, only: [:create, :destroy] collection do get 'search' end end resources :users, only: [:show, :index, :search] resources :relationships, only: [:create, :destroy] end
app/views/posts/show.html.erb
<div class="container"> <div class="row"> <div class="col-md-8 offset-md-2"> <%= image_tag @post.image.variant(resize:'800x800').processed %> <br> <br> <br> <h1 class="text-center"> <strong><%= @post.title %></strong> </h1> <div class="row"> <div class="col-2"> <% if @post.user.image.attached? %> <%= image_tag @post.user.image, class:"avatar m-4"%> <% else %> <%= image_tag ("defo.jpg"), class:"avatar m-4"%> <% end %> </div> <div class="col-4 align-self-center"> <a href="/users/<%= @post.user.id %>", class="h5", style="text-decoration: none"> <p class="h3 text-bold "><%= @post.user.nickname %></p> </a> <%= render partial: 'posts/posts', collection: @posts, as: :post %> </div> <%= render 'relationships/follow_button', user: @user %> </div> <%= @post.content %> </div> </div> </div> <hr> <div class="container "> <div class="col text-center text-muted mb-3"> <h4>コメント</h4> <%= @comments_count %> </div> <div class="col-8 mx-auto"> <% if @comments %> <% @comments.each do |comment| %> <% if user_signed_in? %> <p> <strong><%= link_to comment.user.nickname, "/users/#{comment.user_id}" %>:</strong> <%= comment.text %> </p> <% else %> <p> <strong> <%= comment.user.nickname %>:</strong> <%= comment.text %> </p> <% end %> <% end %> </div> <div class="row "> <div class="col-8 mx-auto"> <% if current_user %> <hr> <%= form_with(model: [@post, @comment], local: true) do |form| %> <div class="form-group mt-3"> <%= form.text_area :text, placeholder: "コメント", rows: "2", class: "form-control" %> <div class="text-right"> <%= form.submit "SEND", class: "btn btn-outline-secondary "%> <% end %> </div> </div> <% else %> <strong><p class="text-center">※※※ コメントするにはログインしてください ※※※</p></strong> <% end %> </div> </div> <% end %> </div> </div> <div class="container" style="margin-bottom:200px;">
試したこと
元の記事のコメント欄やこちらの質問でもあったようにrelationshipsコントローラの記述を
params[:relationship][:follow_id]の部分をparams[:follow_id]に訂正してみました。
それだと下記のエラーが出ます。
undefined method `id' for nil:NilClass
その後にhidden_field_tag :follow_id, user.idの部分をf.hidden_field :follow_id, user.id に修正して見ましたがエラー内容は変わりませんでした。
エラーメッセージがidが無いなっているのビューを表示させているposts_controller.rbのshowメソッドの中で@userを定義すると、エラーはなくなるのですがフォローボタンが表示されませんでした。
他にも自分なりに考えて色々とやってみたのですが解決できずにいます。
どうかよろしくおねがいします。
補足情報(FW/ツールのバージョンなど)
ruby_version 2.6.5
Rails 6.0.3.4
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/10/31 07:16
2020/10/31 10:27 編集
2020/10/31 10:54