いいねボタンを作成するための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を入れることでデフォルトで画像が挿入できる