LoginSignup
2
2

More than 1 year has passed since last update.

【Ruby】 Ruby On Railsでポートフォリオを作ってみた

Last updated at Posted at 2020-10-20

■はじめに

 Ruby on Rails で簡単なアプリを作成したので、苦労したポイントや
 工夫した点を今後の備忘録としてメモしたいと思い、記事を書きました。

■環境構築

 ・Mac
 ・Gitインストール済み
 ・Ruby 2.6.5
 ・Rails 6.0.3.4
 ・Visual Studio Code

■アプリの概要

ユーザー同士で服をシェアできるアプリです。普段私が服を買うとき、他人が着ている服を参考に買うことが多いため、自分たちが持っている服の写真や来てみての感想、値段などをシェアできるアプリがあると便利だと思い、作成致しました。

■データベース設計

今回使用するのは以下の3つのテーブルです。ユーザー(user)は複数の服(fuku)を投稿できます。
さらに、中間テーブルを用いることで、ユーザーは投稿された服にいいね(likes)を押すことができます。

usersテーブル

column type
id string
name string
email string
profile_image_id string

fukusテーブル

column type
id string
title string
body text
user_id integer
image_id string

likesテーブル(中間テーブル)

column type
id string
user_id integer
fuku_id integer

deviseの実装

ログイン認証機能を作る際、1から自分で全て作ると時間がかかるため、簡単に実装できるdeviseを使用しました。

$rails generate devise :install

ログイン機能に必要な設定の方法が出てくるのでコードを書き足します。
さらに、deviseに基づいたUserモデルを作成します。

$rails g devise User

この時、deviseに基づいたUserモデルはデフォルトでemailとpasswordカラムしかもっていないので、migrationファイルにnameとprofile_image_idを書き足します。

$rails g migration add_name_to_users name:string profile_image_id:string
$rails db:migrate

新規登録用のviewにもprofile_imageとnameのフィールドを追加します。

new.html.erb
  <%= f.label :プロフィール画像 %>
  <%= f.attachment_field :profile_image %>  
  <%= f.text_field :name, autofocus: true, placeholder:"名前", autocomplete: "name" %>

これでユーザーの新規登録機能が実装できたと思ったのですが、新規登録画面で名前やプロフィール画像を設定しても
データベースに反映されませんでした。調べたところ、deviseではデフォルトで新規登録する際はメールアドレスとパスワードしか受け取らないことが判明しました。
以下のようにapplication.controllerにストロングパラメーターを記載することで、追加したカラムも受け取れるようになりました。

application.controller.rb
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :profile_image])
end

Refileの実装

userモデルとFukuモデルそれぞれに画像を投稿する機能を実装したいので、refileを使うことにしました。
他にも似たようなgemにcarrierwaveがありますが、refileはcarrierwaveの作者がその後継として作ったもので比較的新しいものだそうなので、今回はrefileを使用しました。
Qiitaのこちらの記事を参考にしました。
https://qiita.com/salvage0707/items/2614c97a1f256027ef71

中間テーブル

投稿された服に対していいねを押せる機能を実装します。

必要な処理

①「いいねしたユーザーのid:user_id」と「いいねされた服のid:fuku_id」が「中間テーブル:likesテーブル」に保存される。
②「いいね」「いいね済み」によっていいねボタンが切り替わる

Likeモデル

まずは、「いいねしたユーザー」と「いいねされた服」を保存するテーブル(likesテーブル)を作ります。

$rails g model like user_id:integer fuku_id:integer
$rails db:migrate

アソーシエイション

モデルに対してアソーシエイションを記述していきます。
UserとFukuは1対多、
UserとLikeは1対多、FukuとLikeも1対多なので、

user.rb
has_many :fukus
has_many :likes
fuku.rb
belongs_to :user
has_many :fukus
like.rb
belongs_to :user
belongs_to :fuku

となります。

ルーティング

投稿された服に対していいねをつけるため、likesはfukus内にネストさせました。
resourceは一行書くだけでルーティングが自動育成されるので非常に便利だと感じました。

 resources :fukus do
      resources :likes, only:[:create, :destroy]
 end

コントローラー

likesコントローラーを作ります。

$rails g controller likes

次に服の詳細ページで、ログインしているユーザーがいいねを押せるよう、viewを編集します。
ログインしているユーザーが既にいいねを押した場合と押していない場合とで異なる動作を行うようにします。

app/views/fukus/show.html.erb
<% if Like.find_by(user_id:current_user.id, fuku_id:@fuku.id) %>
 <%= link_to 'いいね済み', fuku_likes_path(@fuku), method: :delete %>
<%else%>
 <%= link_to 'いいね', fuku_likes_path(@fuku), method: :post %>
<% end %>

likesコントローラーを以下のように記載し、createアクションでログイン中のユーザーのlikesテーブルに、いいねを押したユーザーと投稿のidを格納します。
destroyアクションでいいねの取り消しを行っています。

likes_controller.rb
def create
 @like=Like.new(user_id:current_user.id, fuku_id:params[:fuku_id])
 @lika 
 redirect_back(fallback_location: root_path)
end

def destroy
 @like =Like.find_by(user_id:current_user.id, fuku_id:params[:fuku_id])
 @like.destroy
 redirect_back(fallback_location: root_path)
end

次に、ユーザー詳細ページでいいねした投稿を見れるようにコントローラーとviewを編集します。

@fukus→各ユーザーが投稿した服のuser_idを取得
@likes→各ユーザー押したいいねのuser_idを取得

users_controller.rb
def show
    @user=User.find_by(id:params[:id])
    @fukus=Fuku.where(user_id:@user.id)
    @likes=Like.where(user_id:@user.id)
end
app/users/show.html.erb
  <% @likes.each do |like| %>
         <% fuku=Fuku.find_by(id:like.fuku_id)%>
         <%= link_to(fuku_path(fuku)) do %>
          <%=attachment_image_tag fuku,:image,class:"thumbnail150" %>
         <%end%>
  <%end%>

以上でいいね機能の実装は完了です。

補足

before_action :authenticate_user!

コントローラーの先頭に記載することで、そこで行われる処理はログインユーザーによってのみ実行可能となる。
また、例えばindexアクションのみはログインしていないユーザーをでも行えるようにしたい場合は下記の通り記述する。

class FukusController < ApplicationController
  before_action :authenticate_user!, except: [:index]

 def index
    @fukus=Fuku.all
  end

  def show
    @fuku=Fuku.find_by(id:params[:id])
  end
end

今後学習したいこと

自分でゼロからアプリを作ることによって最低限のCRUD処理などの知識はついたと思います。まだまだエラーが度々発生しますが、似たような記事を参考にすることで、自分で調べて解決する力が付いたと思います。今後もっと学習を継続し、作成したアプリに例えばユーザー同士でメッセージができる機能、服のブランドや種類、価格帯によって検索をかけられる機能などを追加したいです。また、私はフロントエンドの実装が苦手なので、その辺の勉強も併せてやりたいです。

2
2
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
2
2