Quick Clean Restroom(仮)の開発

Quick Clean Restroom(仮)の開発を開始しました。

 

ようやくEC2上に一部デプロイできたので、ブログを書いてみました。

 

外出中に綺麗で快適なトイレを見つけることは、意外と大変な挑戦です。公共トイレはあっても、常に綺麗とは限りません。そんな時、Quick Clean Restroomがあなたの役に立ちます。このアプリケーションは、最寄りの綺麗なトイレをリアルタイムで探し出し、トイレに関する詳細情報を提供します。

 

アプリケーションの使い方
Quick Clean Restroomは使いやすさを重視しています。利用者は簡単にサイトにアクセスし(https://cleanrestrooms.net/posts)、現在地から近い綺麗なトイレを探すことができます。Googleマップと連携しているため、地図上で直感的に最適なトイレを見つけられます。

※お金の都合上、日常的にEC2を稼働していないため、アクセスしてもエラーになります。

 

現在実装されている主な機能

①施設一覧情報:GPSを利用し、周囲にある綺麗なトイレを表示

②施設詳細情報:クリックすることで、選択したトイレの詳細情報、清潔度、設備の有無を表示

③ルート検索:GPSを利用し、現在地から最適なルートで清潔なトイレへと案内します。

  


データベース設計

ER図

 

画面遷移図

画面遷移図

 

技術構成

フロントエンド:HTML CSS Javascript

バックエンド :Rails 7.0.0

インフラ   :EC2 S3

API      :Google Maps API Directions API

第32回 Active Record と Active Storage のメソッド一覧

Ruby on Railsは、ウェブアプリケーションの開発を効率化するための強力なフレームワークです。このフレームワークには、データベース操作に関連するメソッドを提供するActive Recordと、ファイルのアップロードと管理を支援するActive Storageという2つのコンポーネントが含まれています。この記事では、Active RecordとActive Storageでよく使用されるメソッドを整理して紹介します。

Active Record メソッド

レコードの作成と保存

  1. new(attributes)
  2. create(attributes)
    • 新しいレコードを生成してデータベースに保存します。

レコードの検索

  1. find(id)
    • 主キー(通常はID)を使用して特定のレコードを取得します。
  2. where(conditions)
    • 指定された条件に一致するレコードを取得します。

レコードの更新と削除

  1. update(attributes)
    • 指定された属性の値をレコードに一括で更新します。
  2. destroy または delete
    • レコードを削除します。destroy はコールバックをトリガーし、delete は高速な削除操作を行います。

データのソート

  1. order(ordering)
    • レコードの順序を指定します。昇順または降順でソートできます。

関連データの操作

  1. has_many および belongs_to
    • 関連するテーブル間のリレーションシップを設定します。
  2. includes(associations)
    • 関連データを一括で読み込みます。N+1問題を解決します。

Active Storage メソッド

ファイルのアタッチメント

  1. attach(io, filename: nil, content_type: nil)
    • ファイルをアタッチ(関連付け)します。
  2. attached?
    • ファイルがアタッチされているかどうかを確認します。
  3. detach
    • ファイルのアタッチを解除します。

ファイルの操作

  1. blob
    • アタッチされたファイルのバイナリデータやメタデータにアクセスします。
  2. variant(resize: '100x100')
    • 画像のリサイズやバリエーションを作成します。
  3. url
    • アタッチされたファイルのURLを取得します。

Active RecordとActive Storageは、Ruby on Railsの中核的な機能であり、データベース操作とファイルの操作を簡素化し、効率化するために提供されています。これらのメソッドを活用することで、Railsアプリケーションの開発がスムーズに行えます。

第31回 Railsのストロングパラメータ: permitとmergeの使い分け

Railsアプリケーションにおいて、コントローラーでパラメータを扱う際のセキュリティは極めて重要です。ストロングパラメータは、不正なマスアサインメントを防ぎ、アプリケーションを保護するためのメカニズムです。主に**permitmerge**の二つのメソッドが使われます。

permitメソッド

**permit**メソッドは、許可されたフィールドのみをコントローラー内で安全に使えるようにするために使用されます。これにより、フォームを通じてユーザーが送信できるパラメータを厳格に制限することができます。

例えば、部屋を作成する際には部屋の名前と関連するユーザーIDが必要です。以下のように**permit**メソッドを使用して、これらのパラメータを許可します。


def room_params
  params.require(:room).permit(:name, user_ids: [])
end

このコードでは、**:nameuser_idsの配列を許可しています。user_ids**の配列は、部屋にアサインされるユーザーをチェックボックスなどで選択した場合に使われることが多いです。

mergeメソッド

一方で、**merge**メソッドはフォーム外のデータをストロングパラメータに安全に追加するために使われます。これは主に、フォームには存在しないが、サーバー側で処理が必要なパラメータを追加する場合に便利です。

例えば、メッセージを作成する際には、ログイン中のユーザーのIDをメッセージと関連づける必要がありますが、これはフォームを通じて送信されるべきではありません。セキュリティを考慮して、サーバー側で**current_user**を利用してこの情報を追加します。


def message_params
  params.require(:message).permit(:content).merge(user_id: current_user.id)
end

この方法により、**:contentというキーでフォームから送信されたデータを許可し、user_idcurrent_user**のものとして明示的にセットします。これにより、ユーザーは自分のIDを直接送信したり、操作したりすることができなくなり、サーバー側で正確なユーザーIDをメッセージに関連付けることが保証されます。

まとめ

ストロングパラメータを使用することで、Rails開発者はアプリケーションの安全性を維持しながら、ユーザーからのデータを柔軟に扱うことができます。**permitはフォームからのデータを許可するために、merge**はフォーム外のデータを安全に追加するために使用します。これにより、ユーザー入力を適切に制御し、アプリケーションを安全に保つことが可能になります。

第30回 パスヘルパーの使い方

 

Railsのパスヘルパー:引数ありと引数なし

Railsのルーティングシステムは、パスヘルパーという便利なメソッドを提供して、ビューやコントローラーからアプリケーション内の特定のパスを簡単に参照できるようにしています。これらのヘルパーは二つの主要なカテゴリーに分けることができます:引数を必要としないパスヘルパーと、引数を必要とするパスヘルパーです。

引数を必要としないパスヘルパー

引数を必要としないパスヘルパーは、リソースの特定のインスタンスを指定せずに使用できるルートへのURLを生成します。最も一般的な例は**root_path**です。

redirect_to root_path

このヘルパーは、アプリケーションのルートURL、つまりホームページへのパスを生成します。これは通常、ユーザーが最初にアクセスするページであり、ログアウト後のリダイレクトや、ナビゲーションバーのホームリンクなどで使用されます。

引数を必要とするパスヘルパー

一方、引数を必要とするパスヘルパーは、特定のリソースやアクションへのパスを生成する際に使用されます。これらは通常、モデルのインスタンスやIDを引数として受け取ります。

例えば、特定の**Roomオブジェクトの詳細ページへのパスを生成するには、room_pathヘルパーを使用し、それにRoom**のインスタンスまたはIDを引数として渡します。


@room = Room.find(params[:room_id])
redirect_to room_path(@room)

このヘルパーは、与えられた**Room**オブジェクトに対応する詳細ページへのパスを生成します。このパターンは、リソースの編集、更新、削除など、特定のアクションに紐付いたパスを生成する際にも使われます。

まとめ

パスヘルパーは、Railsアプリケーションのルーティングを簡単にし、コードの可読性を高めるための強力なツールです。引数なしで使えるパスヘルパーはシンプルなルートへのリンクを提供し、引数を必要とするパスヘルパーはモデル固有のパスを生成する際に役立ちます。これらの区別を理解することで、開発者はアプリケーション内のナビゲーションを効率的に管理できます。

第29回 データベースからのデータの取得

RailsActiveRecordクエリのベストプラクティス

Railsアプリケーションでは、データベースからデータを取得する際に様々なActiveRecordクエリが使用されます。適切なクエリを選ぶことで、パフォーマンスを向上させるとともに、コードの可読性や保守性を高めることができます。

Eager Loadingを使用したクエリ


@messages = Message.includes(:user)

このクエリでは、**Messageの全レコードを取得し、それに関連するUserオブジェクトも一緒にデータベースから取得します。これは「Eager Loading」と呼ばれるテクニックで、ビューでメッセージとそれに関連するユーザー情報を一覧表示する際に非常に有効です。includes**メソッドを使用することで、N+1クエリ問題を防ぐことができ、アプリケーションのパフォーマンスを大幅に改善することが可能になります。

単純な全レコードの取得


@messages = Message.all

**Message.allは、Message**テーブルの全レコードを取得する最もシンプルなクエリです。ただし、このクエリでは関連するユーザー情報は取得されません。必要に応じてメッセージに紐づくユーザー情報を取得するためには、追加のクエリが必要になります。ビューでユーザー情報を表示する必要がない場合や、特定のメッセージに関連するユーザー情報のみを遅延ロードしたい場合に適しています。

特定のレコードの取得


@message = Message.find(params[:id])

**findメソッドは、与えられたidに一致する単一のMessageオブジェクトを取得します。これは主に、メッセージの詳細ページを表示したり、メッセージを編集・削除する際に使用されます。

間違ったクエリの使用


# これは誤りです
@message = Message.find(params[:room_id])

上記のコードは間違っています。**Messageオブジェクトを取得するためにroom_idを使用するべきではありません。room_idは、Roomオブジェクトに関連付けられていることを意味し、メッセージの識別子ではありません。適切には、関連するRoom**オブジェクトを取得し、その後でその部屋に属するメッセージを取得するべきです:


@room = Room.find(params[:room_id])
@messages = @room.messages

この例では、**Roomオブジェクトが持つmessages**アソシエーションを介して、関連するメッセージを取得しています。

まとめ

データを取得する際には、そのデータの使用方法と必要性を考え、最も効率的なクエリを選ぶことが重要です。

第28回 Railsでフォームを関連付ける - ラベルとフィールドの基本

フォームの構築は一般的なタスクの一つです。Railsが提供する**form_withヘルパーは、このプロセスを簡単かつ効率的にするための強力なツールです。

 

フォームのラベルと入力フィールドを関連付ける理由

アクセシビリティユーザビリティの観点から、フォームのラベルは関連する入力フィールドと関連付けるべきです。ラベルが関連付けられている場合、ユーザーはラベルをクリックするだけで入力フィールドにフォーカスできます。

コード例

ユーザーの名前を入力するシンプルなフォームを示しています。


<%= form_with model: @user do |form| %>
  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>
  <!-- 他のフィールドとサブミットボタン -->
<% end %>

このコードでは、**:nameシンボルはform.labelform.text_field**の両方で使用されており、これによりRailsは自動的に両者を関連付けます。

生成されるHTML

上記のコードから生成されるHTMLは以下のようになります。

<div class="field">
  <label for="user_name">Name</label>
  <input type="text" name="user[name]" id="user_name" />
</div>

このHTMLでは、**<label>タグのfor属性が<input>タグのid**属性と一致しています。この一致が重要で、これによりラベルと入力フィールドが関連付けられます。

まとめ

Railsの**form_with**を使用する際には、フォームのフィールドとラベルを適切に関連付けることで、ユーザビリティアクセシビリティを高めることができる。

第27回 Railsのrenderメソッドの応用

 

Railsの**render**メソッドは、コントローラーとビュー間で非常に重要な役割を果たします。

コントローラーでのrenderの使用例

  1. デフォルトのビューのレンダリング

    • コントローラー: **PostsControllerindex**アクション

    • ビュー: app/views/posts/index.html.erb

    • 動作: Railsは自動的に**index.html.erb**をレンダリングします。

    • コード例:

      
      def index
        @posts = Post.all
      end
      
      
  2. 特定のビューの指定

    • コントローラー: **PostsControllershow**アクション

    • ビュー: app/views/posts/special_show.html.erb

    • コード例:

      
      def show
        @post = Post.find(params[:id])
        render 'special_show'
      end
      
      
  3. 部分テンプレート(パーシャル)のレンダリング

    • コントローラー: **PostsControllernew**アクション

    • パーシャル: app/views/posts/_form.html.erb

    • コード例:

      
      def new
        @post = Post.new
        render partial: 'form'
      end
      
      
  4. 異なるフォーマットのレンダリング

    • コントローラー: **UsersControllershow**アクション

    • コード例:

      
      def show
        @user = User.find(params[:id])
        render json: @user
      end
      
      
  5. フォーム入力の失敗時のレンダリング

    • コントローラー: 例えば**PostsControllercreate**アクション

    • ビュー: app/views/posts/new.html.erb

    • 説明: フォームの入力が失敗した場合、**render :new**を使用して新規作成フォームを再表示します。

    • コード例:

      
      def create
        @post = Post.new(post_params)
        if @post.save
          redirect_to @post
        else
          render :new
        end
      end
      
      

ビューでのrenderの使用例

  • パーシャルのレンダリング
    • ビューファイル: app/views/posts/show.html.erb
    • パーシャル: app/views/posts/_comment.html.erb
    • ビュー内のコード: <%= render 'comment', comment: @comment %>

これらの例から、**render**メソッドの多様な使用法を理解し、Railsアプリケーションで効率的にビューを管理する方法が分かります。特に、部分テンプレートの再利用や、異なるフォーマットのレスポンス提供は、アプリケーションの開発と保守において非常に重要です。