いいねボタンを作成するためのcreateアクションを作成
初めに
- Progateを学習中に躓いたところを中心にアウトプットするのと同時に備忘録がてらに記事を書いていきます!
現状
likes_controller内にcreateアクションを定義したが中身は空のまま。
createアクションに関するルーティングは
post "likes/:post_id/create" => "likes#create"
自分が書いたコード
likes_controller
class LikesController < ApplicationController
before_action :authenticate_user
def create
@like = Like.new(user_id :@current_user.id, post_id :@post.id
@like.save
redirect_to("/posts/#{params[:post_id]}")
end
- authenticate_userはapplicarion_controllerで
def authenticate_user
if @current_user == nil
flash[:notice] = "ログインが必要です"
redirect_to("/login")
end
end
としている。
- @postが定義されていないのでエラーの対象となる。
実際のコード
likes_controller
def create
@like = Like.new(user_id :@current_user.id, post_id :params[:post_id])
@like.save
redirect_to("/posts/#{params[:post_id]}")
end
いいね!を作るためにはユーザーのidと投稿のidの2つが必要。
例えばLike.new(user_id: 1, post_id: 2)となるとuser1がpost1にいいねしたというコードになる。
post_id :@post.id→post_id :params[:post_id]に変更した。
createのルーティングよりpost "likes/:post_id/create" => "likes#create"からpost_idは送られていて、 Like.newに入れれば良いのでpost_id :params[:post_id]となる
結語
post_idの値はルーティンで記載されてあるURLのpost_idに含まれている。
paramsはURLの値を捕まえる役割がある。
before_actionを特定の場所に効かせるために
初めに
- application_controllerで以下のものを定義して、ログインしていないユーザーに対してアクセス制限をかけるようにした。
def authenticate_user
if @current_user == nil
flash[:notice] = "ログインが必要です"
redirect_to("/login")
end
end
- 今回はposts_controllerの全てのアクション、users_controllerのindex,show,update,editアクションのみに制限をかけたい
問題
- アクセス制限をかけたくないhomes_controllerのtop,aboutアクションにもアクセス制限がかかっていた。
コード
application_controller
class ApplicationController < ActionController::Base
before_action :set_current_user
before_action:authenticate_user
def set_current_user
@current_user = User.find_by(id: session[:user_id])
end
def authenticate_user
if @current_user == nil
flash[:notice] = "ログインが必要です"
redirect_to("/login")
end
end
end
posts_controller
class PostsController < ApplicationController
before_action :authenticate_user
def index
@posts = Post.all.order(created_at: :desc)
end
def show
@post = Post.find_by(id: params[:id])
end
def new
@post = Post.new
end
def create
@post = Post.new(content: params[:content])
if @post.save
flash[:notice] = "投稿を作成しました"
redirect_to("/posts/index")
else
render("posts/new")
end
end
def edit
@post = Post.find_by(id: params[:id])
end
def update
@post = Post.find_by(id: params[:id])
@post.content = params[:content]
if @post.save
flash[:notice] = "投稿を編集しました"
redirect_to("/posts/index")
else
render("posts/edit")
end
end
def destroy
@post = Post.find_by(id: params[:id])
@post.destroy
flash[:notice] = "投稿を削除しました"
redirect_to("/posts/index")
end
end
users_controller
class UsersController < ApplicationController
before_action :authenticate_user ,{only:[:index,:show,:edit,:update]}
def index
@users = User.all
end
def show
@user = User.find_by(id: params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(
name: params[:name],
email: params[:email],
image_name:"default_user.jpg",
password: params[:password]
)
if @user.save
session[:user_id] = @user.id
flash[:notice] = "ユーザー登録が完了しました"
redirect_to("/users/#{@user.id}")
else
@email = params[:email]
@password = params[:password]
@name = params[:name]
render("users/new")
end
end
def edit
@user = User.find_by(id: params[:id])
end
def update
@user = User.find_by(id: params[:id])
@user.name = params[:name]
@user.email = params[:email]
if params[:image]
@user.image_name = "#{@user.id}.jpg"
image = params[:image]
File.binwrite("public/user_images/#{@user.image_name}",image.read)
end
if @user.save
flash[:notice] = "ユーザー情報を編集しました"
redirect_to("/users/#{@user.id}")
else
render("users/edit")
end
end
def login_form
end
def login
@user = User.find_by(password: params[:password], email: params[:email])
if @user
session[:user_id] = @user.id
flash[:notice] = "ログインしました"
redirect_to("/posts/index")
else
@email = params[:email]
@password = params[:password]
@error_message = "メールアドレスまたはパスワードが間違っています"
render("users/login_form")
end
end
def logout
session[:user_id] = nil
flash[:notice] = "ログアウトしました"
redirect_to("/login")
end
end
home_controller
class HomeController < ApplicationController
def top
end
def about
end
end
原因
application_controllerでbefore_action:authenticate_userを定義しているために全てのcontrollerにアクセス制限をかけてしまっていた。
application_controllerでbefore_action:authenticate_userを削除してアクセス制限をかけたいcontrollerでbefore_action:authenticateを定義する。
結語
application_controllerでbefore_actionを定義してしまうと全てのcontrollerに影響を与えてしまう
application_controllerで定義したメソッドは他のcontrollerで利用できるので 今回はアクセス制限をかけたいcontroller内でbefore_actionを定義しなくてはいけない。
before_actionを特定の場所に効かせるために
初めに
- application_controllerで以下のものを定義して、ログインしていないユーザーに対してアクセス制限をかけるようにした。
def authenticate_user
if @current_user == nil
flash[:notice] = "ログインが必要です"
redirect_to("/login")
end
end
- 今回はposts_controllerの全てのアクション、users_controllerのindex,show,update,editアクションのみに制限をかけたい
問題
- アクセス制限をかけたくないhomes_controllerのtop,aboutアクションにもアクセス制限がかかっていた。
コード
application_controller
class ApplicationController < ActionController::Base
before_action :set_current_user
before_action:authenticate_user
def set_current_user
@current_user = User.find_by(id: session[:user_id])
end
def authenticate_user
if @current_user == nil
flash[:notice] = "ログインが必要です"
redirect_to("/login")
end
end
end
posts_controller
class PostsController < ApplicationController
before_action :authenticate_user
def index
@posts = Post.all.order(created_at: :desc)
end
def show
@post = Post.find_by(id: params[:id])
end
def new
@post = Post.new
end
def create
@post = Post.new(content: params[:content])
if @post.save
flash[:notice] = "投稿を作成しました"
redirect_to("/posts/index")
else
render("posts/new")
end
end
def edit
@post = Post.find_by(id: params[:id])
end
def update
@post = Post.find_by(id: params[:id])
@post.content = params[:content]
if @post.save
flash[:notice] = "投稿を編集しました"
redirect_to("/posts/index")
else
render("posts/edit")
end
end
def destroy
@post = Post.find_by(id: params[:id])
@post.destroy
flash[:notice] = "投稿を削除しました"
redirect_to("/posts/index")
end
end
users_controller
class UsersController < ApplicationController
before_action :authenticate_user ,{only:[:index,:show,:edit,:update]}
def index
@users = User.all
end
def show
@user = User.find_by(id: params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(
name: params[:name],
email: params[:email],
image_name:"default_user.jpg",
password: params[:password]
)
if @user.save
session[:user_id] = @user.id
flash[:notice] = "ユーザー登録が完了しました"
redirect_to("/users/#{@user.id}")
else
@email = params[:email]
@password = params[:password]
@name = params[:name]
render("users/new")
end
end
def edit
@user = User.find_by(id: params[:id])
end
def update
@user = User.find_by(id: params[:id])
@user.name = params[:name]
@user.email = params[:email]
if params[:image]
@user.image_name = "#{@user.id}.jpg"
image = params[:image]
File.binwrite("public/user_images/#{@user.image_name}",image.read)
end
if @user.save
flash[:notice] = "ユーザー情報を編集しました"
redirect_to("/users/#{@user.id}")
else
render("users/edit")
end
end
def login_form
end
def login
@user = User.find_by(password: params[:password], email: params[:email])
if @user
session[:user_id] = @user.id
flash[:notice] = "ログインしました"
redirect_to("/posts/index")
else
@email = params[:email]
@password = params[:password]
@error_message = "メールアドレスまたはパスワードが間違っています"
render("users/login_form")
end
end
def logout
session[:user_id] = nil
flash[:notice] = "ログアウトしました"
redirect_to("/login")
end
end
home_controller
class HomeController < ApplicationController
def top
end
def about
end
end
原因
application_controllerでbefore_action:authenticate_userを定義しているために全てのcontrollerにアクセス制限をかけてしまっていた。
application_controllerでbefore_action:authenticate_userを削除してアクセス制限をかけたいcontrollerでbefore_action:authenticateを定義する。
結語
application_controllerでbefore_actionを定義してしまうと全てのcontrollerに影響を与えてしまう
application_controllerで定義したメソッドは他のcontrollerで利用できるので 今回はアクセス制限をかけたいcontroller内でbefore_actionを定義しなくてはいけない。
ヘッダーのログアウトのリンクを押してもログアウトリンクに遷移しない原因
初めに
- Progateを学習して躓いたところのアウトプットをすることで学習効率を上げる目的とともに備忘録として記事を書きます
問題
- ヘッダーのログアウトのリンクを押してもログアウトリンクに遷移しない

考えられること
ログアウトリンクに誤りがある
ログアウトに関するルーティングに誤りがある
user_controllerのlogoutアクションに誤りがある
関連するコード
routes.rb
Rails.application.routes.draw do post "logout" => "users#logout" get "login" => "users#login_form" post "login" => "users#login" post "users/:id/update" => "users#update" get "users/:id/edit" => "users#edit" post "users/create" => "users#create" get "signup" => "users#new" get "users/index" => "users#index" get "users/:id" => "users#show" get "posts/index" => "posts#index" get "posts/new" => "posts#new" get "posts/:id" => "posts#show" post "posts/create" => "posts#create" get "posts/:id/edit" => "posts#edit" post "posts/:id/update" => "posts#update" post "posts/:id/destroy" => "posts#destroy" get "/" => "home#top" get "about" => "home#about" end
users_controller
class UsersController < ApplicationController
def index
@users = User.all
end
def show
@user = User.find_by(id: params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(
name: params[:name],
email: params[:email],
image_name:"default_user.jpg",
password: params[:password]
)
if @user.save
session[:user_id] = @user.id
flash[:notice] = "ユーザー登録が完了しました"
redirect_to("/users/#{@user.id}")
else
@email = params[:email]
@password = params[:password]
@name = params[:name]
render("users/new")
end
end
def edit
@user = User.find_by(id: params[:id])
end
def update
@user = User.find_by(id: params[:id])
@user.name = params[:name]
@user.email = params[:email]
if params[:image]
@user.image_name = "#{@user.id}.jpg"
image = params[:image]
File.binwrite("public/user_images/#{@user.image_name}",image.read)
end
if @user.save
flash[:notice] = "ユーザー情報を編集しました"
redirect_to("/users/#{@user.id}")
else
render("users/edit")
end
end
def login_form
end
def login
@user = User.find_by(password: params[:password], email: params[:email])
if @user
session[:user_id] = @user.id
flash[:notice] = "ログインしました"
redirect_to("/posts/index")
else
@email = params[:email]
@password = params[:password]
@error_message = "メールアドレスまたはパスワードが間違っています"
render("users/login_form")
end
end
def logout
session[:user_id] = nil
flash[:notice] = "ログアウトしました"
redirect_to("/login")
end
end
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>TweetApp</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<header>
<div class="header-logo">
<%= link_to("TweetApp", "/") %>
</div>
<ul class="header-menus">
<li>
<% if session[:user_id] %>
現在ログインしているユーザーのid:
<%= session[:user_id] %>
<li>
<%= link_to("投稿一覧", "/posts/index") %>
</li>
<li>
<%= link_to("新規投稿", "/posts/new") %>
</li>
<li>
<%= link_to("ユーザー一覧", "/users/index") %>
</li>
<li>
<%= link_to("ログアウト","/logout")%>
</li>
<% else %>
<li>
<%= link_to("TweetAppとは", "/about") %>
</li>
<li>
<%= link_to("新規登録", "/signup") %>
</li>
<li>
<%= link_to("ログイン", "/login") %>
</li>
<%end%>
</li>
</ul>
</header>
<% if flash[:notice] %>
<div class="flash">
<%= flash[:notice] %>
</div>
<% end %>
<%= yield %>
</body>
</html>
原因
ログアウトリンクに{method: "post"}が記述されていなかった。
<%= link_to("ログアウト","/logout",{method: "post"})%>
{method: "post"}がないことでログアウトに関連するpost "/logout" =>"users#logout"を実行できなかったと考えられる
link_toではHTTP methodを指定してあげないとgetになってしまうので get "/logout" =>"user#logout"を探してしまうことになってしまう
結語
- link_toはmethodを指定しなければHTTPメソッドをgetとしてしまう
ユーザーを特定する
初めに
Progateを学習して躓いたところを中心にアウトプットし、備忘録としても活用していきます。
ログインするユーザーを特定していく。
find_byメソッドを利用していく。
今回はpasswordとemailの2つからユーザーを特定していく
ユーザーテーブルからフォームで入力された値と一致するユーザーを見つけ出し、@userに代入する
users_controller
def login
@user = User.find_by(email: params[:email], password: params[:password])
end
if文を使って存在するユーザーなのか、存在しないユーザーなのか判別する。
users_controller
def login
@user = User.find_by(email: params[:email], password: params[:password])
if @user
flash[:notice] = "ログインしました"
redirect_to("/posts/index")
else
render("users/login_form")
end
if @user ではemailとpasswordが一致するユーザーがいるのならばというコード。
一致するユーザーがいた場合、flash[:notice] = "ログインしました"が表示される。
そして投稿一覧ページに遷移する。
もし一致するユーザーがいなければ、ログインページに戻る。
ユーザーがいなかった場合、エラーメッセージを表示させる
users_controller
def login
@user = User.find_by(email: params[:email], password: params[:password])
if @user
flash[:notice] = "ログインしました"
redirect_to("/posts/index")
else
@error_message = "メールアドレスまたはパスワードが違います"
render("users/login_form")
end
- バリデーションによって表示させるエラーメッセージではないので、@error_message = "メールアドレスまたはパスワードが違います"のように 自作でエラーメッセージを作る。
login_form.html.erb
<div class="form-body">
<% if @error_message %>
<div class="form-error">
<%= @error_message %>
</div>
<% end %>
<%= form_tag("/login") do %>
<p>メールアドレス</p>
<input name="email" value="<%= @email %>">
<p>パスワード</p>
<input type="password" name="password" value="<%= @password %>">
<input type="submit" value="ログイン">
<% end %>
</div>
- reder先のlogin_form.htmlに@error_messageを貼り付け、メールアドレスとパスワードが一致しない場合はエラーメッセージが表示できるようにす る。
結語
find_byメソッドを利用して登録したユーザーを見つけ出す。
if 文を利用して登録済みユーザーが未登録ユーザーなのかを判別する。
flashメッセージを利用してログインができたことを表示させる。
バリデーションではないエラーメッセージの場合は@error_messageのような自らエラー表示用のインスタン変数を作り出し、メッセージを記述し、 表示させたいビューに貼り付ける。
ユーザー登録時に初期画像を設定する
初めに
- Progateを学習して躓いたところをアウトプットすることで学習効率を上げるとともに備忘録がてらに日記を書いていきます。
結論
- ユーザー情報を入力する空箱の中に初期画像の情報を入れておく
前提
- usersテーブルにimage_nameカラムを追加しておく
ターミナルにてrails g migration users image_name stringを行う 生成したマイグレーションファイルにadd_column :テーブル名, :カラム名, :データ型でchangメソッドの中に記載を行う *rails db:migrateを行う
ユーザー登録する際に初期の画像を設定するために
public/user_imagesに初期画像のdefault_user.jpgを用意する
ユーザー登録時にimage_nameカラムの値がdefalt_user.jpgになるようにする
def create
@user = User.new(
name: params[:name],
email: params[:email],
image_name: "default_user.jpg"
)
if @user.save
flash[:notice] = "ユーザー登録が完了しました"
redirect_to("/users/#{@user.id}")
else
render("users/new")
end
end
結語
- User.newという空箱の中に image_nameカラムを入れ、その値にすでに決まっているdefault_user.jpgを入れることでデフォルトで画像が挿入できる
ユーザー登録時に初期画像を設定する
初めに
- Progateを学習して躓いたところをアウトプットすることで学習効率を上げるとともに備忘録がてらに日記を書いていきます。
結論
- ユーザー情報を入力する空箱の中に初期画像の情報を入れておく
前提
- usersテーブルにimage_nameカラムを追加しておく
ターミナルにてrails g migration users image_name stringを行う 生成したマイグレーションファイルにadd_column :テーブル名, :カラム名, :データ型でchangメソッドの中に記載を行う *rails db:migrateを行う
ユーザー登録する際に初期の画像を設定するために
public/user_imagesに初期画像のdefault_user.jpgを用意する
ユーザー登録時にimage_nameカラムの値がdefalt_user.jpgになるようにする
def create
@user = User.new(
name: params[:name],
email: params[:email],
image_name: "default_user.jpg"
)
if @user.save
flash[:notice] = "ユーザー登録が完了しました"
redirect_to("/users/#{@user.id}")
else
render("users/new")
end
end
結語
- User.newという空箱の中に image_nameカラムを入れ、その値にすでに決まっているdefault_user.jpgを入れることでデフォルトで画像が挿入できる