fluid_27’s blog

勉強した内容をアウトプットするためのブログ

初デプロイまでの道のり② Linux勉強しないとダメだな。と気づいた話。

 

まず、この記事では何も解決しません。

エラーで苦しんだり、とにかく知識を得たい!という人はこの先は読まないでください。

 

これまでの道のり

AWSを使っての初デプロイってこんな険しい道なのか。。

 

というか、それ以前にAWSだけでなく、Linuxの知識が無さすぎてホントに細かい部分で躓いてしまうので、結果ものすごい遠回りをしてしまっている。

 

先日、AWSで初デプロイを試みるも、何故か

We're sorry, but something went wrong.

の表示のままで(エラーログなし)、メンターからのアドバイスFileZillaを使って、デプロイしているアプリをただ rails new しただけのアプリと置き換えて、AWSの方に原因があるのか、アプリの方に原因があるのか確認することに。

 

 

ようやくFilezillaAWS側と繋いで、置き換えてみると 502 のサーバーエラー。

やっぱりAWS側の問題?と思いながら、とりあえずエラーログを見てみよ。

 

、、、ってunicornないじゃん。

いや、unicornはgemに記述するわけだから、ただrails newしただけのアプリには無いに決まってるか。

 

ということで、vi でgemの内容を変更。

そして、bundle install実行。

There was an error while trying to write to `/var/www/rails/xxx(アプリ名)/Gemfile.lock`.

It is likely that you need to grant write permissions for that path.

 えー、書き込みの権限ないよ。

って言われました。

 

単に書き込み権限付ければいいんだろうなぁ。と思ったのですが、今まで参考記事とかでやみくもにchownとかchmodとか使っていたので、改めて「それぞれどういう意味だっけ」と思ってググってみました。

 

下記サイトが非常に分かりやすくまとめてくれていて、大変参考になりました。

qiita.com

 

Linuxコマンド

chmod、chownなどの違い
  • chmod (change mode) ファイルやディレクトリのアクセス権限を変更
  • chown (change owner) ファイルやディレクトリの所有者を変更
  • chgrp (change group) ファイルやディレクトリのグループを変更

他にも755など数値での権限の表し方。

-rwx--x--xなどのアルファベット10文字での、ファイルに対するアクセス権限の表し方が分かりやすくまとめられていました。

 

他にもLinuxで調べて、へぇって思ったこと。

 

パーミション権限の確認

$ ls -al ファイル名・ディレクトリ名

 

今現在ログインしているユーザーを調べる

$ who

    もしくは

$ user

 

ユーザーやパスワードに関する情報は /etc/passwd に

ユーザー情報に関する整合性が失われてしまう可能性があるので、手動では変更しないように、とのこと。

 

lessコマンド

たまに参考記事とかで出ていたコマンド。catとどう違うんだ?って思ってましたが、lessだとテキストファイルを1画面ずつ表示できる。とのことです。

 

書式

less ファイル名

   もしくは

コマンド | less

と書いて、別のコマンド結果を1画面ずつに表示することもできる。

 

  • Enterで次の行
  • スペースキーで次の画面に進める
  • 上下矢印キーでスクロールも可能
  • qで終了

 

 

 と、色々Linuxコマンド調べたところでGemfile書き込めるよう権限をつけてみようとするも、うまくいかない。。なぜ。。

 

というか、Linuxに関して分かってなさすぎな件

ここまできて気づきましたが、自分は全然Linuxの知識が全然ない。。

デプロイする際にQiitaなどで紹介されている記事に書かれている通りに、その都度実行してきました。

が、一度腰を据えて、ちゃんとLinux勉強しないとダメだな。

 

一刻も早く「デプロイしたい」という気持ちですが、ちゃんと体系的に勉強できる時間というのはすごく貴重だと思うので、むしろ今の内にしっかり基礎を勉強しようと思います。

 

ということで、以前購入していた

・「Linux標準教科書 ver3.0,2」と

・Udemy教材「これだけでOK!AWS認定〜」

で、LinuxAWSの勉強します。

 

まだまだ初デプロイへの道は続きます。

 

特に中身ない記事をご覧いただきありがとうございました。

頑張ってAWSでのデプロイまで漕ぎ着けたいと思います。

初デプロイまでの道のり① FileZillaを使ってようやくAWSと繋いだ話

PF用に作っていたアプリをデプロイしてみよう。と思い、初デプロイにAWSで作ってみることにしました。

qiita.com

を参考にしながらデプロイを進めました。

 

記事に書いてある処理を全て終えてみても何故か

We're sorry, but something went wrong.

の表示が消えない。。

 

  • unicorn 起動している
  • nginx 起動している
  • MySQL 起動している

そしてlogを見に行ってもエラーはどこも出ていない。。

 

手がかりゼロの状態で、メンターに頼ったところ

「とりあえず、アプリ自体に問題があるのか、AWSの方に問題があるのかをはっきりさせた方がいい」

ということで、ただrails newしただけのアプリを試しに作り、それを立ち上げてるAWSインスタンスと結び付け、ちゃんとサーバー立ち上がるかをチェックしてみることに。

 

そして、AWSインスタンスに結びつける際に「便利だよー」と教えてくれたのがFileZillaだった。

 

FileZillaとは・・・

サーバー内のファイルを修正したり、サーバー内にファイルを送ったりするための無料で使えるファイル転送ソフト(FTPソフト)のことです。

そしてググって見た記事を参考に使ってみるも、そもそもAWS側と繋がらない(泣)

っていうか、この「ユーザー名」や「パスワード」は何の??

AWSにログインする時のもの??

 

ターミナルでAWSに繋ぐ時は

ssh xxx(アプリ名)_key_rsa

で繋いでいるんだけど、、、

と、超初心者の私はオロオロし、とりあえず思い当たるユーザー名とパスワードで手当たり次第試しみるも、繋がらず。。

 

ググってみても、その辺りの情報を書いてくれてる記事は全然ないし(当たり前か)。AWSのドキュメントはめちゃめちゃ分かりづらいし。。

「こんなところで」というところで思いっきり躓いて時間取られました。

 

そして、ググり続けていて、見つけました。

AWSのドキュメント!!

 

それは、「ユーザー名」と「パスワード」ではなく「ユーザー名」と「鍵ファイル」で繋いでみた時のこと、、、

今まで

エラー:      非アクティブになってから 20 秒後に接続がタイムアウトになりました

エラー:      サーバーに接続できません 

というエラーしか出ていなかったのに

 

エラー:      FATAL ERROR: No supported authentication methods available (server sent: publickey,gssapi-keyex,gssapi-with-mic)

エラー:      サーバーに接続できません

というエラーが出ることに気がつきました。

 

早速、上記のエラー文でググってみると、

あるAWSのドキュメントに辿りつきます。

aws.amazon.com

上記のページで解決方法を順番に試してみようと思い、最初の「正しいユーザー名を確認する」というところから着手しました。

詳細ページに遷移してみると、次の一文が!!

Amazon Linux2またはAmazonLinux AMIの場合、ユーザー名は ec2-userです。

 

いや、そらみんな知ってますよね。たぶん。

一応

ユーザー名「ec2-user」と、鍵ファイルで繋いでみることに。

 

と、秒でつながりました!!!(歓喜

えー、なんで!?!? もしやと思って、ec2-userのユーザー名でも何度かトライしていたのに。。

思い返すと、その時は「ユーザー名」と「パスワード」で繋ごうとしていました。

ということは「パスワード」が間違っていたということか。。

 

物凄い初心者チックなミスで時間を相当使った私はこうして「FileZillaで繋ぐ」を覚えました。

ただ、ここは「初デプロイ」という本山では、まだ3合目どころか1合目あたり、、、まだまだAWSでの初デプロイへの道は続くのであります。

MySQLが動かなくなったので、ググって起動させた話

 

エラー状況

デプロイに際してSQLiteからMySQLに切り替え、ローカルでサーバーを立ち上げようとした際にエラー発生。

 

解決方法

いっぺんMySQLをアンインストール後、改めてインストール。で解決。

 

エラー発生から解決までの道のり

ローカルでサーバー立ち上げようとしたら、

Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

というエラーが。

 

ググってみると

  1. /tmp/mysql.sock ファイルがない可能性が。

その場合はファイルを作成する。

$ sudo touch /tmp/mysql.sock

 

 2.config/database.yml 内で socketの指定先が違っている可能性。 

 
 config/database.yml
 
    default: &default
      pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
      username: root
      password:
      socket: /tmp/mysql.sock # ←ここの部分

 の部分を

    socket: /var/lib/mysql/mysql.sock

に変更でなおった。という記事が。

 

上記、1、2共に試してみる。

 

そして、rails db:create

してみると、

.. ERROR! The server quit without updating PID file (/usr/local/var/mysql/XXXXXXXX.local.pid).

 というエラーが。

今度は、上記のエラー文でググってみる。

 

と、別の記事で

一度、mysqlを削除、インストールし直したらなおったという記事を発見。

別にDB削除しても構わないので、やってみます。

$ sudo rm -rf /usr/local/var/mysql

$ brew uninstall mysql

$ brew install mysql

で、mysqlスタートしてみる。

$ mysql.server start

 Starting MySQL .

 SUCCESS!

成功したーー!!

 

改めて

$ rails db:create

$ rails db:migrate

 で解決しました。

 

ここら辺のエラー解決は記事がたくさんあるので、初学者にとって助かりました(泣)

 

 

参考記事

Rails アプリ起動時のMysqlエラー を解消 (Mysql2::Error::ConnectionError ・ Can't connect to local MySQL server through socket '/tmp/mysql.sock') - Qiita

mysqlがどうしても起動しない - Qiita

PF作るに当たって覚えたことの整理 2020.2.7

PF作るに当たって覚えたことの整理 2020.2.7

 

 

if文でなく、or演算で値を代入する ||

rails tutorialにも記載ありますが、

変数 = データA || データB

としておけばデータAがあればデータAを変数に代入。もしなければデータBを代入する。というコードを書けます。

例)

@post = Post.where(user_id: @user.id) || Post.new(post_params)

上記で、user_idが@user.idに適合するpostを。

なければ新しくpostを生成する。

というコードをすっきり書けます。

 

 

while end の中で i++を使ってエラーにハマった話

unexpected end_of_input

expecting end

と出てくるので、

「これってendが足りなかったり、多い時に出てくるエラーだよなぁ」

と思ってendを数えて見たのですが、合ってる。。

試しにwhile~ end を消してみると、うまくいく。

ということはwhile ~ end の記述がおかしい。と思い、見てみるも構文通り。。

っていうかwhile自体、そんな難しい構文じゃないし。

 

で、結果からいうと

while i <= 10 do

  i++

end

という記述になっていたから。

 

これを

while i <= 10 do

  i+= 1

end

こう書き換えて解決。

 

エラーメッセージの表示のさせ方

rails tutorialでflashを使ってエラーメッセージを表示させる方法をやったなぁ。

と思い、PFにも適用することに。

 

controllerのflashを作りたい箇所で

controller.rb

flash[:danger] = "表示させたいエラー文"

を記述

 

application.html.erb

<% flash.each do |message-type, message| %>

  <div class="alert alert-<%= message-type %>"><%= message %></div>

<% end %> 

 をbodyの中に記述。

 

上記では

[:danger]

を使用しているが、他にも

[:success]

[:info]

[:warning]

を使っても自動的にスタイルがあたる。

 

 

 外部キー制約でデータを削除できなくなった話

テストで作った、Chatデータを削除しようとしたら

・・・foreign key constraint fails 

というエラー文が出てきて、削除できない。。

ちなみに、モデルの関連づけでいうと

User.rb

has_many :chats, foreign_key: :user_id

 

Shop.rb

has_many :chats, foreign_key: :shop_id

 

Chat.rb

belongs_to :shop

belongs_to :user

has_many :messages, foreign_key: :chat_id

 

Message.rb

belongs_to :chat

となってます。

 

外部キー制約

調べてみると、外部キー制約の関係で削除できないみたい。

外部キー制約については詳しく解説してある記事がたくさんあるので、そちらを参照して頂ければと思いますが、上記の例でいうと

messageはchatと関連付けられていて、Messageテーブルのデータには必ずそれぞれchat_idが入っています。 

が、あるchatを勝手に削除してしまうと、chat_idが空のmessageができてしまうので、それを防ぐためのものです。

 

dependent: :destroy

外部キー制約の関係で、chatを削除する際にエラーが起きてしまっていました。

エラーを出さずに削除するために それぞれにdependent: :destroy を追記して、無事解決しました。

User.rb

has_many :chats, foreign_key: :user_id, dependent: :destroy

 

Shop.rb

has_many :chats, foreign_key: :shop_id, dependent: :destroy

 

Chat.rb

belongs_to :shop

belongs_to :user

has_many :messages, foreign_key: :chat_id, dependent: :destroy

 

Message.rb

belongs_to :chat

 

optional: true

エラーを解決のために色々な記事を調べていたら、

 belongs_to :chat, optional: true

というようにoptional: trueを記述しているコードがあって、optional: true って、なんじゃらほい?と思って調べてみると、どうやらbelongs_toの外部キーのnilを許可するもの。みたいです。

つまり、外部キーがnilであってもDBに保存されるということですね。

 

 

 

カラムを配列で定義しようとしたものの、デメリットがある為やめた話

一緒に勉強している仲間から「カラムを配列の形で保存している」と聞き(serialize)、そういうことが出来るのか!と思った自分は、早速自分のポートフォリオでもその技を活用しようとしました。

 

ただ、よくよく調べてみるとデメリットがあり、要約すると

 

「serializeを使うと、実際の保存はYAMLまたはJSONで保存されることになり、ある日、急にrailsの都合で形式が変わった際に手動でserializeを使っていたデータを書き換えなければいけなくなる」

「仕様変更(型変更)に弱い」

「遅くなる」

 

といったところです。

詳しくは下記で解説してくれてます。

ActiveRecord serialize / store の甘い誘惑を断ち切ろう - Qiita

 

ので、配列にして保存したかったのは数字を文字列化したもので、それを取り出した際にviewに順番に貼り付けていく。ということをしたかっただけなので、

いったん配列の形のまま、データに文字列として保存し、

”[”10”, ”11”, ”12”, ”13”]"

それを取り出した際にsplitで分割して、最初と最後についてしまう"[", " ]"を削除することにしました。

["10", "11", "12", "13"]

とちゃんと配列として再び扱えるようになりましたとさ。

PF作るに当たって覚えたことの整理 2020.2.4

PF作るに当たって覚えたことの整理 2020.2.4

 

 

binging.pryを終了させる時は

exit

、、のはずが、終了させられず、ググったところ

exit!

で終了させられるとのこと。ただ、ローカルサーバーも自動的に終了します。。

 

 

配列の中に値があるか調べる include?

a = ["1", "2", "3"]

a.include?("2")

=> true

 

 

配列の中に値が何番目にあるのか調べる index

引数で指定した要素がオブジェクトの何番目にあたるかを整数で返す。

オブジェクトが配列の場合は配列の何番目にあるかを整数で返す。

注意点として数える際は0番目から始まる。

例)

s = "abcdefghijk"

puts s.index("cd")

=> 2

 

a = ["abc", "def", "ghi"]

puts a.index("def")

=> 1

 

 

配列の中の値を場所を指定して書き換える

配列[置き換えたい場所] = 新しい要素

例)

ary = ["abc", "def", "ghi"]

ary[1..2] = ["123", "456"]

ary

=> "abc", "123", "456"

 

ary = ["abc", "def", "ghi"]

ary[0] = ["123", "456"]

ary

=> "123", "456", "def", "ghi"

という風に要素をたすこともできる。

 

三項演算子の書き方

上のincludeと共に、この辺りは一回勉強したけど、実際使う際に「どうやって書くんだっけ?」となったので、確認の意味で。

 

構文)

条件 ? trueの際実行する処理 : falseの際実行する処理

例)

a = 10

a == 15 ? puts "same" : puts "different"

=> "different"

 

 

テーブルのデータ全部消す destroy_all

 

モデルクラス.destroy_all

例)

User.destroy_all

 

また、条件付きでの削除だったら

User.where(id: 1..10).destroy_all

というふうに書けるみたいです。

PF作るに当たって覚えたことの整理 2020.2.3

PF作るに当たって覚えたことの整理

2020.2.3

 

画像自体をリンクにする

link_to 画像の名前, 遷移させたいページの場所

例)

 <%= link_to image_tag("img_logo.png"), show_path%>

 

 

テーブルから条件をつけてデータを取り出す

絞り込んで特定のカラムだけ取り出す pluck

テーブル名.where(カラム名: "条件").pluck(:取り出したいカラム)

例)

 User.where(gender: "male").pluck(:name)

 とするとuserテーブルの内の男性(male)だけの名前(name)が取得できる。

 ["太郎", "次郎"]

 というように配列で受け取れる

 

 複数のカラムを取得する際は

 User.where(gender: "male").pluck(:id, :name)

 とすると

 [[1, "太郎"], [2, "次郎"]]

 と取得できる

 

レコードの個数を指定する limit

テーブルからデータをとってくる際に、個数に制限をかけて取得したい場合

モデル名.limit(n)

で個数を制限できます。

例)

 先頭から3つのレコードを取得

 @discography = Discography.limit(3)

 

 5つ目から3つのレコードを取得

 @discography = Discography.limit(3).offset(4)

 

 

配列から順番に取り出していく方法 slice!

要素.slice!(引数)

で要素から指定した引数にあたる値を配列から取り出す。取り出された値を返してくれる。

a = ["a", "b", "c"]

a.slice!(1)

=>"b"

a

=>"a","c"

 

範囲指定

a = ["a", "b", "c"]

a.slice!(0, 1)

=>"a", "b"

a

=>"c"

 

 

railsでの複数checkboxの設置、値の取得の方法

オプションで{multiple: true}を設定

 

 

日付の関連の取得方法

 

今日の日付 Date.today

=>2021-02-03

 

日にちを整数で取得(1~31) mday

Date.today.mday

=>3

 

月を取得 month

Date.today.month

=>2

 

年を取得 year

Date.today.year

=>2021

 

1月1日からの通算日を取得(1~366) yday

Date.today.yday

=>34

 

暦週を取得 cweek

Date.today.cweek

=>6

 

曜日 wday

曜日を数値の0~6で返してくれる。(0=>日、1=>月、 2=>火・・)

例)

 weekday = %w[日 月 火 水 木 金 土]

 weelday[Date.today.wday]

 =>水

 

 

hidden_fieldとhidden_field_tagの使い方

form_forやform_tagの中で使う場合は

f.hidden_field

単体で使う場合は

hidden_field_tag を使う

 

f.hidden_fieldの使い方

f.hidden_field :カラム名, :値

例)

<%= form_for @user do |f| %>

 <%= f.text_field :name %>

 <%= hidden_field_tag :user_id, current_user.id %>

 <%= f.submit "送信" %>

<% end %>

 

コントローラ側で

name を取得する場合

 params[:user][:name]

user_idを取得する場合

 params[:user_id]

 

hidden_field_tagの使い方

hidden_field_tag :変数(第一引数), 渡したい値(第二引数)

例)

 <%= hidden_field_tag :email, @user.email %>

 コントローラ側でparams[:email]で値を取り出せる。

 

ちなみに、下記サイトでより細かく説明してあります。

form_forとform_tagでのparamsの違いなども説明してあり、非常に参考になりました。

【Rails】form_forの使い方をマスターしよう! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

 

 

 

form_with, form_forでのプルダウンの設置方法

f.select :保存先のカラム名, [["選択肢A", "実際に保存させる内容"], ...], include_blank: '選択してください'

 

例)

 <%= form_with model: @food do |f| %>

  <%= f.select :fruit, [["りんご", "りんご"], ["みかん"m "みかん"], [”ばなな”, "ばなな"]], include_blank: "選択してください" %>

  <%= f.submit '送信' %>

 <% end%>

rails tutorial第13章 自分用メモ

rails tutorialで躓いた自分のために、より理解が進むようザックリと内容を整理してメモとしてまとめていきます。

 

完全に自分用のメモです。

2020.12.28 ver.

 

Rails tutorial 第13章で学習する内容

  • Micropostモデルの作成
  • MicropostモデルとUserモデルを1対多の関係として繋ぐ
  • micropost(投稿)を新しい順に表示されるよう設定する
  • ユーザーを削除したらそのユーザーの投稿も削除されるよう設定する
  • userコントローラーにあったlogged_in_userをmicropostコントローラーでも使えるようにapplicationコントローラーに移す
  • feedメソッドを定義し、フィードの原型を作成
  • carrierwave gemを利用し、画像アップロード機能の実装
  • アップロードされる画像のサイズやフォーマットに対し、バリデーションを実装
  • ImageMagicをインストールし、アップロードする画像をリサイズできるように

 

 

おさらい。今回or前回までに分かった内容

  • MicropostモデルとUserモデルは1対多の関係なので
  • models/user.rbにhas_many :micropostを記述。
  • models/micropost.rbにbelongs_to :userを記述。またジェネレーターで作成する時にrails g model Micropost content:text user:references とすると自動で記述してくれる。
  • 上記のようにbelongs_to :userを記述するとMicropostテーブルにuser_idカラムが追加される
  • micropostを新しい順に表示させるにはmodels/micropost.rbにdefault_scope -> { order(created_at: :desc) }を記述する
  • ユーザーが削除された時にそのユーザーが紐づいた投稿が削除されるようにmodels/user.rbのhas_many :micropostにオプションでdependent: :destroyを追加する
  • pluralizeメソッドは指定された単語の複数形を返すメソッド
  • request.referrerは1つ前のurlを返すメソッド

 

現時点で?な点

  • プロックオブジェクトを返すとは?

 

当方、エンジニアになるべく学習している身なので、これ違うよ!と言う点や補足ありましたら、ぜひご指摘お願いいたします。