現場で使える Ruby on Rails 5速習実践ガイドを読んで

今回、Ruby on Railsの学習にあたり、タイトルの書籍を読んで学習しました。
その感想を記載します!

良かったところ

タスク作成アプリを機能ごとに関係、仕組みを説明しながら進められる形だったので、理解は比較的しやすいと感じました。
セキュリティ面にも触れられているため、実際の開発時に、意識すべき点について知ることができた点も良いと感じました。そのほかにも、Railsでアプリを作成する際に、関わってくる周辺技術についても簡単にではありますが触れられており、その点もの理解の助けになったりしました。

学んだこと

Railsの基礎的な情報から、実装する際の便利な機能について、これから開発するに向けて意識する点などについて学ぶことができました。 バージョンが異なるため、異なる点がどこかを比べながら進めることができました。

難しかったこと

書籍販売時のRailsのバージョンが5系であるのに対し、筆者はバージョン7系で実施していたためバージョン差異を埋めながらかつ理解しながらおこなっていたため苦労しました。
メジャーバージョンが異なるため、導入されているgemが異なる点
(主にTurbo)や、記述の差異form_tag,form_forからform_withが利用されている点や、少しフォルダ構成が異なるなどがあり、ことあるごとに止まってしまうということもありました...
その他に、学んだ点で触れた開発時に意識する点についてですが、筆者自身が開発経験がほほゼロのため、なかなか想定としてあげられていたケースがイメージできず。こういう場合はこうするべきといった指針が
なかなかイメージできなかった点も読み進めていくにあたり苦労しました。
この点については、自分で実装する際に、再度確認しながら実装したいと思います!

引き続き、学習を継続してまいります!

REST API 備忘録

  • そもそもAPIとは
    Application Programming Interfacenの略称で
    異なるソフトウェアやサービスがお互いに通信し、機能やデータを共有するための規約や手段を提供しているもの
  • WebAPI
    APIの中でHTTPプロトコルを利用して、Web上で通信やデータのやり取りを行うAPIの一種
  • REST APIとは
    WebAPIの一種でRESTの原則に則って設計されたAPIを指す
    RESTの原則に則ったAPIをRESTfulなAPIとも呼ぶ

    • RESTとは
      Representation State Transferの略称で
      設計原則の一種となる
      ロイ・フィールディングが提唱した原則で、以下の設計原則に則ったAPIをRESTfulなAPIと呼ぶ
      また、全てに則って設計されていないといけないということはなく
      要件等に合わせて設計される

      • RESTにおける6つの原則
        1. クライアントとサーバーの分離
          クライアント側でUIやUXを担当し、サーバー側でデータ処理の部分を担当することによって役割を分離する
        2. ステートレス性
          サーバー側でクライアント側の状態を保持しないようにする
           リクエスト時に必要な情報を全て含めて提供し、サーバー側で情報を保持しないようにする

        3. キャッシュ制御
          クライアント側はサーバー側からのレスポンスをキャッシュ(一時的にデータを保持しておく仕組み)しておくことができ、再取得の必要をなくす。
          主にレスポンスヘッダーに含まれ、キャッシュの可否や有効期限について制御できる

        4. 統一インターフェース
          4つの原則で成り立っている
          1. リソースの識別
            リソースが一意に特定できること
          2. メッセージのやり取り
            HTTPメソッドを用いてクライアントとサーバー間でリソースに対する操作を行えること
          3. 自己記述的メッセージ
            レスポンスを見た時に、その情報を見ることで、他に参照しなくても内容が理解できること
          4. HATEOAS
            レスポンスに関連する情報をリンクとして含めて、次可能なアクションを提示することができる
        5. レイヤー化システム
          Webサーバー、DBサーバー、APサーバーなど階層を分けて機能を分離する。
          階層を分けて、それぞれを独立させることで変更が他の階層に影響を与えないようにすることで、保守性や拡張性が向上する
        6. コードオンデマンド
          レスポンスに実行可能はJavaScript等のコードが含まれ、
          それを受けとったクライアントがそれを実行すること。実際には、
          セキュリティ上の観点や、可読性の低下などからあまり実装はされていない。
  • CRUD操作
    movieをリソースとした場合のCRUD操作とその際のURIは以下のようになる

    URI HTTP method
    /movies GET
    /movies/ POST
    /movies/{movie_id} PUT
    /movies/{movie_id} DELETE

達人に学ぶDB設計 徹底指南書を読んで

良かったところ

自分がDB設計をする立場になった際にどの点を意識すれば良いかを
とても細かく記載されていたところが良かったです。
設計上意識しないといけない点を集中的に触れていたため、
意識しないといけない点がわかりやすかったです。

学んだところ

前提として、筆者はDB設計経験はないため、あくまで想像の範疇ではあるが、
作成する際の意識する点に触れることができ、いざ作成するとなった時のこの書籍で触れたことを
意識できるというインデックスを頭に入れることができ、
また、SQLがどのような流れでデータを取得しているのかなど意識したことがなかったので
開発視点での動作に触れることができました。

難しかったところ

学んだ点で触れたが、筆者は設計経験がないため、想像しづらい部分が多々あったことです。
経験者からすれば、また、書籍で挙げられてあようなテーブルになっているようなアプリケーション
に触れたことのある方であれば、理解しやすかったのかもしれません。
筆者の場合はそれがない状態でのスタートだったので、読み進めるのに時間がかかりました。

感想

上記の点を踏まえた上で、DBの設計方針、
設計時の注意点を網羅的に学ぶことができる良書であると感じました。
設計時には記載されていた点をきちんと意識できるよう注意点をリスト化するなども
良いかもしれません。

スッキリわかるSQL入門v3を読んで

よかったところ

CRUDについての基礎的な部分を網羅的にわかりやすく説明されており、
各章ごとに章末のまとめや、練習問題など復習を行う上でとても復習がしやすかったです。
また、練習問題も簡単すぎず、少し考えないといけない問題もあり、きちんと理解に
つながるようになっていました。内容も、理解しやすいようにわかりやすく説明されており、
初心者にもわかりやすいようになっているように感じました。

もう少しこれが欲しい

この本には、総復習としてたくさんの問題がドリルとして提供されているのですが、
ドリル解答の答えに解説がないため、なぜこのような記述になるのかという理解が
なかなかできない部分がありました。いまでも何点か理解ができていない部分があります...
ドリルに対する解答にも解説があるととても助かると感じました。

学んだこと

SQL自体は自己学習で触れることが何度かありましたが、
今回の書籍が一番記憶に定着しやすいように感じました。
基本的な構文だけでなく、テーブル作成、削除、権限付与、トランザクション
テーブルの正規化などDB操作に関する基礎知識を網羅的に学ぶことができました。

難しかったこと

書籍最後のドリルの各セクションの最後の方の問題が個人的に難易度が高かったです。
また、正規化が特に苦手で、画像からエンティティと属性の切り出しがとても時間がかかりました。
また、自分で切り出した属性と解答を確認した際の、属性の数がなかなか合わず、
切り出し方も異なることが多くとても苦戦しました。
また、切り出した属性をもとに第一正規形にする際の、繰り返し項目を切り出す点が
なかなか理解できず苦戦しました。まだまだ、慣れが必要ですが、何度も繰り返し慣れたいと感じました。

optparseの使い方

optparseについて

Rubyスクリプトコマンドライン引数を受け取る時にオプションを指定する場合に
利用したoptparseについて使い方を備忘録として残します!

optparseコマンドラインで実行する際に
受け付けるオプションを定義し、実行したい処理をその定義のブロックに記述することで
そのオプションを引数に受け取った際の処理を指定できる

オプションの定義

処理の流れは以下のようになる 1. OptionParseの生成
2. オプションの登録
3. opt.parse(ARGV)でコマンドラインを実際にparseする

require 'optparse'
opt = OptionParser.new

opt.on('-a') {|v| p v}

opt.parse!(ARGV)
p ARGV

OptionParser#onメソッドの引数でオプションを定義し、指定された時の
処理をブロックに定義する
ブロックパラメーターには引数が指定されたことを示す、trueが渡される
また、OptionParser#onが実行された時点ではブロックの処理は実行されず
parseが実行された時点で初めて、ブロックに渡された処理が実行される

ruby sample.rb -a foo
#=> true
#=> ["foo"]

sample.rbにオプション-aとその引数fooを渡すと結果は上記のようになる
-aが指定されたことを示すtrueが渡されpによってその結果が表示され、
その引数がARGVに渡され表示される。
ARGVはスクリプトに与えられた引数を表す配列であり、
スクリプト実行時に渡した引数はARGVに渡され配列に格納される

ruby sample.rb -a foo bar hoge
#=> ["foo", "bar", "hoge"]

parseすることによって初めて定義した処理が実行されるが、
parse!はオプションが取り除かれた状態で解析される
逆に、parseの場合はオプションが取り除かれず変数に渡すと
取り除かれた状態になる。

require 'optparse'
opt = OptionParser.new

opt.on('-a') {|v| p v}

argv = opt.parse(ARGV)
p ARGV
#=> ["a"] 
p argv
#=> ["-a", "a"]

以下のようにブロックパラメータを記述しないで実行することも可能

require 'optparse'
opt = OptionParser.new
opt.on('-a') do
  puts '-aオプションが指定されました。'
end

opt.parse!(ARGV)

登録していないオプションを指定するとエラーとなる

ruby sample.rb -b
#=>`<main>': invalid option: -b (OptionParser::InvalidOption)

以上、簡単な使い方です!

プロを目指す人のためのRuby入門を読んで

今回、このタイトルの参考書を読了したたためこの場で感想を記述する。
この本はRuby初心者が、Rubyのお作法を知るにはとても良い参考書だと感じた。 内容は、初心者が理解しやすいよう難しいコードは書かれておらず、 また、参考書で過去に出てきた箇所が登場した際に、振り返りやすいように、 どこを参照すべきか参照先が記述されていたりと、親切な部分もありがたかった。

最初は、Rubyの基礎的な記述方法を丁寧に説明してあり、
条件分岐や繰り返し処理、ハッシュや配列の処理、正規表現など
についても詳しく書かれており、基礎で重要な箇所についてとても丁寧に説明されていた。
その際には、よく利用されるメソッドなども併せて解説してあり、
Rubyで表現する際のメソッドの知見が、基礎的な部分ではあるが広がった。
その他にも、実務でそれが利用されるのかどうかなどにも触れられていたりと、 分量はとても多いが、基礎を知る上ではさまざまは表現方法に触れることができ、 初心者レベルではあるが表現の幅がとても広がるのでとても良い参考書だと感じる。

少し難易度が高いと感じたのはクラスの概念を学ぶ際の、selfについてだったと感じる。 他の言語でも同じだと思うが、selfの書かれる位置によってそのselfが指すものが変わってくる。
そのため、理解するのに少し時間がかかった。また、それでもまだ100%とはいかないので、 これからRubyを触れるにあたって、少しずつ理解を深めていきたい。

この本は、とても網羅的に記述されており、一通り記述されているコードを試し、
どのように処理されるかを試しながら、理解を深めたが、書かれていたこと全てを理解
できたわけでは当然ないため、これからもRubyをたくさん触れることで、理解を深めていきたい。
それでも、初心者として、表現方法のインデックスが頭の中にできたのはとても大きいように感じる。

読んだ本は以下

https://www.amazon.co.jp/o/ASIN/B09MPX7SMY/gihyojp-22

RailsアプリをDocker上で動かすための設定

前提

dockerをインストールしていること。
今回の設定はローカル環境(作業PC)上で動作する際の設定になります。
テスト環境や本番環境では、設定する箇所が異なる点や、セキュリティ上DBのユーザー情報などを
環境変数でハードコードすることはありません。また、それらの設定方法は今回記述しておりません。

実行環境のバージョン

ruby: 3.2.2
rails: 7.0.6
postgres: 12

構築前準備

Dockerコンテナを用意するために必要なファイルの準備

作業箇所は任意とし、以下のファイルを用意する
筆者の作業箇所は~/rails-app とする

Dockerfile   
docker-compose.yml   
Gemfile
Gemfile.lock   
Dockerfileの中身
FROM ruby:3.2.2
RUN apt-get update && apt-get install -y \
  build-essential \
  libpq-dev \
  nodejs \
  postgresql-client \
  yarn
WORKDIR /rails-docker
COPY Gemfile Gemfile.lock /rails-docker/
RUN bundle install
  • それぞれの要素について
FROM ruby:3.2.2

FROMではDockerHubのレジストリからイメージを取得し、取得したイメージを元にコンテナを作成する

RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
nodejs \
postgresql-client \
yarn

コンテナ内でRUN以降のコマンドを実行します。
RUNコマンドはRUNコマンドを実行する度にコンテナのレイヤーが作成されます。
これにより、コンテナ内で、必要なパッケージがインストールされます。

WORKDIR /rails-docker

コンテナ内でWORKDIRで指定したパスに切り替わり、記述以降のコマンドが実行されます。/ルートディレクトリ直下にrails-dockerディレクトリが存在しない場合は作成されます

COPY Gemfile Gemfile.lock /rails-docker/

COPY src dstとなり、作業環境で指定したパス内にあるディレクトリのファイルをコンテナの指定したパスに配置します。srcの起点はdocker run,docker compose buildを実行した箇所から見てになります。COPYでもレイヤーは作成されます。   最後にbundle installでGemfileに記載のパッケージをインストールします。

docker-compose.ymlの中身
#dockerのバージョンを指定します
version: '3'
volumes:
  db-data:
services:
  web:
    build: .
    volumes:
      - .:/rails-docker
    command: >
      bash -c "bundle exec rails db:create && 
               bundle exec rails db:migrate &&
               bundle exec rails s -p 3000 -b '0.0.0.0'" 
    environment:
      - DATABASE_PASSWORD=postgres
    ports:
      - 3000:3000
    depends_on:
      - db
  db:
    image: postgres:12
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
        - 'POSTGRES_USER=postgres'
        - 'POSTGRES_PASSWORD=postgres'
  • volumes(2行目)
    永続化したいデータがある際は作業端末のディレクトリをマウントするのではなくvolumeを作成します。
    以下で作成されたvolumeの確認ができます。
docker volume ls

詳細を確認したい場合は以下であり、このコマンドでマウントされている箇所が記載されているが、
これは作業端末からは見えない。 コンテナを起動する際にVMが内部で立ち上がり、その上でコンテナが起動しており、そのVM上のパスとなる。

docker volume inspect {volume_name} 
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data"
  • services
    この配下に作成するコンテナの情報を記載していく
    今回の場合はweb,dbという名前でコンテナが起動する。
    • build
      ビルドする際の、Dockerfileを探す場所を指定
    • volumes
      local/to/path:remote/to/path
      コンテナと作業端末のディレクトリを共有するために指定する
    • command
      コンテナを起動した時に実行するコマンドを指定できる コマンドが複数行にわたる場合、>command:の横に記載、bash -c "command && command" のように記載することで複数コマンドを実行できる bash -cでダブルクォートで囲まれた文字列をコマンドとして渡すことができる
    • environment
      コンテナ内で利用する環境変数を定義できる 今回はDB接続に利用するパスワードの変数を記述
    • ports
      作業端末とコンテナのポートを紐づける
    • depends_on
      コンテナの依存関係を指定する。サービスの準備が整うまで待つわけではないため注意。今回は軽量なため、問題はない。
    • image
      Dockerfileと同様にDockerHubにあるイメージを取得しコンテナを立ち上げる
      Gemfileの中身
source 'https://rubygems.org'
gem "rails", "~> 7.0.6" 
Gemfile.lockのからファイルを用意
touch Gemfile.lock

準備したファイルを元に構築

  • 以下で、Railsアプリを作成する。 以下では、webコンテナと作業ディレクトリで共有しているディレクトリにアプリのファイル構成が作成され、
    Gemfileが更新されます。Gemfileが更新されるので、 更新された状態で、再度ビルドすることで、Gemfile記載のパッケージがインストールされた状態でイメージを作ることができます。
  docker compose run web rails new . --force --database=postgresql
  • rails-app/config/database.ymlを編集する
    無編集では1つ目のようになっている RailアプリがDBとやりとりをするために2つ目のように 設定を記述する必要がある
default: &default
adapter: postgresql
encoding: unicode

development:
<<: *default
database: myapp_development
  • host,user,port,passwordを追記
default: &default
adapter: postgresql
encoding: unicode
host: db 
user: postgres
port: 5432
password: <%= ENV.fetch("DATABASE_PASSWORD") %>
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  • host
    docker-compose.ymlservices:配下に記述したDBの名前を指定
  • user
    host同様に、environment:で定義した環境変数に指定したユーザを指定
  • port
    postgreSQLがデフォルトで利用するポートを明示的に指定
  • password services:Railsアプリ側のコンテナに定義した
    environment:で指定したものを参照するように指定

イメージを更新した状態で、再度コンテナを起動する

  docker compose up --build -d

起動が完了したら、ブラウザで起動させてRailsのバージョンが記載されたWebページが表示されればOK

参考

クイックスタート:ComposeとRails