アソシエーションを組む時に使う、belongs_to/has_one/has_manyの違いについて。

railsにおいて、アソシエーションを組んでテーブル同士を結びつける時に使うbelongs_to/has_one/has_manyのそれぞれの使い分けについてまとめます。

 

アプリの概要

メルカリのようなフリマアプリで考えていきます。

まず、userテーブル、itemテーブル、purchaseテーブルの3つのテーブルを設計したとします。

userテーブルでuserの情報を管理します。itemテーブルでは商品の情報を管理します。purchaseテーブルには購入履歴を管理します。以下イメージです。

 

gyazo.com

 

アソシエションについて

belongs_toメソッド

商品1つに対して、出品者は1人になるためです。

1つの商品に複数人が出品できないため、商品は必ず1人に所属します。

この状態をbelongs_toの関係といいます。

 

has_oneメソッド

has_oneメソッドは1対1の関係を結ぶメソッドです。

上の図ではitemとpurchaseがそれにあたります。

商品1つに対して、購入履歴は1つになるためです。

親のモデル(今回は商品がなければ、購入履歴がありえないため、itemが親になります。)にhas_oneの記述をします。

子のモデルにbelongs_to(今回はpurchaseが子になります。)の記述を行います。

 

has_manyメソッド

user側からすると出品する商品(item)は複数あります。

つまり1人のuserは複数のitemを持ちます。

この関係をhas_manyの関係といいます。

このuser1人に対して複数商品がある状態を1対多(has_many)の関係にあるといいます。

 

まとめ

belongs_toは1対1の関係で子側(後から作られるもの)のモデルに書く。

has_oneは1対1の関係で親側(先に作られるもの)のモデルに書く。

has_many1対多の関係で複数持つ側のモデルに書く。

Herokuで画像ファイルが壊れて表示されない時の対処方法。

Herokuはデータベースが定期的にリセットされ、画像ファイルが壊れて表示されない。そのため、画像を表示させるためには下記コマンドを用いてデータベースをリセットすることが必要。


heroku run DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rails db:drop db:create db:migrate`

railsでサーバーが起動しない場合の原因

rails sでサーバーを起動し、ローカル環境でブラウザの確認をする機会が多くあると思います。その時、

A server is already running

とターミナルで出て、ブラウザがずっと読み込み続けて開けない時の原因と対策を記録していきます。

 

原因

これは一日の作業後にターミナルやサーバーを立ち上げたまま閉じたり、繋げっぱなしにすると起こるようです。

 

対策

まず、直し方です。

ターミナルにps aux | grep pumaと入力します。

これで状態の確認ができます。すると、

 

ユーザー名    1245  99.9  2.0  4589056 171840   ??  R     9:55PM  20:58.15 puma 3.12.6 (tcp://localhost:3000) [furima-00000] 

ユーザー名   3273   0.0  0.0  4287756    744 s000  S+   11:51AM   0:00.00 grep puma

 

このような記述が帰ってきました。

1つ目の記述を見るとlocalhost:3000でfurima-00000が動いています。とのことなので動作をしている番号を消すため

ターミナルにkill 1245と入力します。

その後、ps aux | grep pumaと入力すると、

ユーザー名   3279   0.0  0.0  4268300    696 s000  S+   11:52AM   0:00.00 grep puma

となり、裏で動いていた処理がなくなりました。

これでrails sすると、正常にサーバーが立ち上がりました。

 

まとめ

原因はサーバーやターミナルを付けっぱなしにしていること。

対策はサーバーが止まったら、

ps aux | grep puma

で状態確認を行う。

不要なタスクをkill 番号、で消す。

ps aux | grep puma

 で動いている処理を再確認する。

1日の作業が終了したら、サーバーを落としてターミナルを切る。電源を落とす。

定期的に起こるようなのでしっかり覚えておきたい。

before_actionの使い方とコードの可読性の上げ方

コントローラーのアクションで下記のような選んだ商品と現在ログイン中のユーザーが同じか確認する記述がありました。何度も同じ記述を繰り返さないためにどうすればいいか記録していきます。

 

 

app/controllers/items_controller.rb
def edit
 @item = current_user.items.find_by(id: params[:id])
 unless @item
 redirect_to root_path
 end
end
 
def update
 @item = current_user.items.find_by(id: params[:id])
 unless @item
  redirect_to root_path
 end
 if @item.update(item_params)
  redirect_to item_path
 else
  render :edit
 end
end

 

上記の場合、コントローラーのアクションで下記のような選んだ商品と現在ログイン中のユーザーが同じか確認する記述がeditアクションとupdateアクションで出てきます。

 

app/controllers/items_controller.rb
@item = current_user.items.find_by(id: params[:id])
unless @item
redirect_to root_path
end

 

コードを簡潔にするためbefore_actionで上記コードをまとめると可読性が上がります。

before_actionは指定したアクションの前に自動で実行する処理を書いておくものです。

before_action+使いまわしたいメソッド名+アクション名で記述します。

 

before_action :correct_user, only: [:edit, :update]
def edit
 
end

def update
 if @item.update(item_params)
  redirect_to item_path
 else
  render :edit
 end
end
private
def correct_user
 @item = current_user.items.find_by(id: params[:id])
 unless @item
  redirect_to root_path
 end
end

 

まとめたい処理をcurrent_userとメソッド化することでbefore_actionで使えるようになります。

 

まとめ

before_actionでコードをまとめることで可読性が上がり、修正時も一部分を修正するだけでよいので、できるだけまとめるように心がけたいですね。

文字列の一部を切り取りたい時の書き方。

任意の文字列の最初の2文字を最後尾に持ってきて
その文字を出力するメソッドを作りたい時の書き方。

出力例:
left2("Hello") → lloHe
left2("Hi") → Hi

def left2(str)
  puts str[2..-1] + str[0..1]  
end

①str[2..-1]で(配列の1文字目は0のため)3文字目から最後、②str[0..1]で最初の2文字を表しています。これを任意の文字列の最初の2文字を最後尾に持ってくるようにすればいいので、①→②の順で記述すればよい。

全角数字について

テストコードで全角数字でないことを確認したい時に困ったのでメモしておきます。

 

一般的な数字は半角数字で111などと入力します。

一方、全角数字は111ですが、これは数字ではなく文字扱いになります。

よって、全角数字は"111"のように""や''のクォーテーションで囲む必要があります。

 

全角数字は普段あまり使われず、調べても出てこないです。

数字は半角だから、全角なら数字ではない扱いになるのか、など仮説を立てて検証するしかなかったようです。

rails db:rollbackでエラーが出てしまい、rollbackできない時の対処方法。

rails db:rollbackができない場合の対処方法をまとめていきます。

  1. マイグレーションファイルの変更方法
  2. rails db:rollbackでstatusがdownにならない時

 

1、マイグレーションファイルの変更方法

マイグレーションファイルはエディタ上では書きかえられますが、そのままでは反映されません。コードを変更する前にターミナルで

rails db:rollback

と入力し一度戻して

rails db:migrate:status

と入力し確認すると 

gyazo.com

 上のようになります。(下から順に一つずつdownになります。)downになったファイルを変更し、

rails db:migrate

と入力するとdownのところがupになり修正が反映されます。

 

2、rails db:rollbackでstatusがdownにならない時

 

何らかの理由でマイグレーションを消すと

********** NO FILE **********

となり、rails db:rollbackでstatusがdownにならなくなります。

その場合、

1.bundle exec raka db:drop

2.bundle exec raka db:create

3.bundle exec raka db:migrate

4.bundle exec raka db:migrate:status

と順番に打つと

gyazo.com

のように********** NO FILE **********が消えます。

その後、

rails db:rollback

と打つと、一番下がdownになり、マイグレーションファイルが変更出来るようになります。