個人アプリ開発 エリア別一覧ページ作成

エリア一覧ページの作成

今回はエリアコントローラを作成し、都道府県ごとのアクションに所属都道府県のデータを持つインスタンスを作成する方法で実装を行いました。
結果かなり冗長なコードになり、もっとスマートにできるはず…とも思いましたが、
URLは/area/tokyoみたいな感じになり、そこは良かったので一旦こちらで進めました。
f:id:kobegoro:20200815200520p:plain

コントローラ作成
$ rails g controller areas
ルーティング編集
ーーー追記ーーー
resources :areas do
    collection do
      get 'tokyo'
      get 'kanagawa'
      get 'chiba'
      get 'ibaraki'
      get 'saitama'
      get 'tochigi'
    end
  end
コントローラ編集
def tokyo
    @groups = Group.where(area: "東京")
  end
ーーー以下略ーーー
ビュー作成(部分テンプレを作成)
[areas/_index.html.haml]
= render "common/header"

.groups-main
  .groups-main--head
    .groups-main--head__wrapper
      %h1
        = @groups[0].area
        の水族館
      %p
        口コミ評価が高い順にご紹介!

    = render "common/lists"
  = render "top/side-bar"

= render "top/footer"

その他の修正

マウスオーバーで説明テキストを表示

下記の箇所は見た目を優先し、アイコンと数字の表示のみにしましたが、
ちょっと内容が分かりにくいと思ったので、カーソルを持って行った時に説明が出るようにしました。
f:id:kobegoro:20200815195209p:plain
CSSで兄弟クラスにホバーアクションをつけられるのは知らなかったので、勉強になる修正でした。
参考:
CSSで実装する、マウスオーバーで表示される吹き出し | Tips Note by TAM

CarrierWaveでアップロードした画像ファイルは全てGit管理下から外す

commitをする度にいつか修正したい...と思いつつ後回しにしてました汗

[.gitignore]
# Ignore uploaded files in development
 /public/uploads/

画像は/public/uploads/に保存される為、そこを.gitignoreに記述してあげるだけ。
毎度のストレスを考えると、まずはじめにやっておくべきでした。

CSSで最後のクラスの指定

繰り返し処理をしているところの最下部にborder-bottomをつけたい。
下記箇所の修正。ちょっと分かりにくいが、border-topのみスタイリングしている状態。
f:id:kobegoro:20200815200030p:plain

[css]
.ranking__box:last-of-type {
  margin-bottom: 25px;
  border-bottom: solid 2px #dbdbff;
}

.class:last-of-type {
繰り返し処理を施している場合、最後のクラスにスタイルを当てる
これも初めての記述でした。今後使えそう。

個人アプリ開発 carrierwaveでハマった

作業内容

今日は各所の微調整を行いました。
・部分テンプレートを作成しリファクタリング
・仮で入れていた箇所のDB連携
・スタイリング修正
・テスト情報の入力

躓き

その中でハマってしまったのが、画像に関して。
テストイメージを入力した際に、以下のように潰れてしまっている
f:id:kobegoro:20200813224214p:plain

以前気づいた時はケータイ画像を使用していたので、単純に拡大しすぎが原因だとスルーしてしまっていました。

・小さい画像を拡大したのが原因か?

→元画像のサイズは大きい

JPEGをサイズ変更したのが原因?

PNGファイルでもダメ

・webアプリでトリミングした画像をUPしてみる(縦横比が変わらないように)

→ダメ

ここでhamlファイル、cssファイルのサイズの指定を外して表示してみることに。
すると画像が極小に表示されてしまいました。
元画像は大きいはずなのになぜ、、、とここで気がつき、carrierwaveのuploderの設定を確認すると、

[app > uploders > image_uploders.rb]
process resize_to_fit: [100, 100]

取り込み画像のサイズ設定を小さくしてしまってました泣
大きい元画像→carrierwaveで小さい画像→拡大して粗くなる、となっていたのが原因でした。
こちらを修正してOKでした。

最初にcarrierwaveをインストールする際に何気なく設定してしまっていましたが、とても学びになりました。
今後も新しいgemを入れる際など、「この記述の意味は?」「値を変えることで例えばどんなリスクがあるか?」などの思考を挟めるように精進していきたいと思います。


毎日いろんなエラーや思った通りにならない事ばかりですが、徐々に建設的に対処法を考えたり、スピード感を持って解決に当たることができるようになっている気がします。(もちろんまだ初心者ですが)

何より少しずつ自信がついてきて、プログラミングを楽しめているのが自分にとっては嬉しいです。
引き続き毎日時間を作ってPDCAを回しつつ精進していきたいと思います。

個人アプリ開発 マイページ作成2

引き続きマイページのビューを編集していきました。

と言ってもほとんど部分テンプレートを使用しているので、実作業箇所は少ないです。

特に問題なく完了しました。

アカウント画像の表示やリンクの作成もスムーズだったので良かったと思います。

まだいいね機能(行った・保存)は作成していない為、該当箇所は仮で作成しました。

f:id:kobegoro:20200812222741p:plain

個人アプリ開発 マイページ作成

ユーザー編集機能作成、プロフィール画像の追加

一度ざっと作成しましたが、編集後updateがうまくできずハマってしまいました。

→スペルミスや記述漏れなど穴が開くほど確認笑
→binding.pryで確認するが、ちゃんと送れている
→理由が不明だった為、devise箇所を作り直しました。

元々user_contorollerのみ使用するお手軽な(?)作成方法をしていた為、

$ rails g devise:controllers users

で作成したregistrations_controller.rbとapprication_controller.rbを編集していきました。
が、結果上手くいかず。

ここでふとviewに

= devise_error_messages!

を入れて、エラー内容を確認できることに気がつきました。

▶︎”password is invailed”のエラー文が出た為、まさかと思いつつバリデーションを確認したところ、passwordに変なバリデーションがかかっていました。なので保存がされなかった。
修正して(一旦バリデーションを外して)、解決。

・まず原因を特定すること
・解決案を柔軟に出すこと
非常に勉強になりました。

作業一覧

コントローラ作成
$ rails g devise:controllers users
モデル編集

passwordのバリデーションを修正
mount_uploader :image, ImageUploader #追加
(テーブルにはimageカラム作成済み)

コントローラ編集
[application_controller]
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  # ログイン済ユーザーのみにアクセスを許可する
  before_action :authenticate_user!

  # deviseコントローラーにストロングパラメータを追加する          
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
  def configure_permitted_parameters
    # サインアップ時にnameのストロングパラメータを追加
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
    # アカウント編集の時にnameとprofileのストロングパラメータを追加
    devise_parameter_sanitizer.permit(:account_update, keys: [:name, :image])
  end

end
編集時のview
[devise_registrations_edit.html.haml]
#account-page.account-page
  .account-page__inner.clearfix
    .account-page__inner--left.account-page__header
      %h2 Edit Account
      %h5 アカウントの編集
      = link_to "ログアウト", '#', class: 'btn'
      = link_to "トップページに戻る", :back, class: 'btn'
    .account-page__inner--right.user-form
      = form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f|
        = devise_error_messages!
        .field
          .field-label
            = f.label :ニックネーム
          .field-input
            = f.text_field :name, autofocus: true
        .field
          .field-label
            = f.label :メールアドレス
          .field-input
            = f.email_field :email
        .field
          .field-label
            = f.label :アカウント画像
          .field-input
            = f.file_field :image
        .actions
          = f.submit "Update", class: 'btn'
ルーティング
resources :users, only: [:show]

devise_for :users, controllers: {
        registrations: 'users/registrations'
}

usersのshowへのルーティングを作成。
その下の「devise_for」の記述でregistrations_controller.rbの内容を有効にする

コントローラ
[app/controllers/users/registrations_controller.rb]
protected
  # アカウント編集後、プロフィール画面に移動する
  def after_update_path_for(resource)
    user_path(id: current_user.id)
  end
[app/controllers/users/apprication_controller.rb]
  # ログイン後、トップページに移動する
  def after_sign_in_path_for(resource)
    root_path
  end
プロフィール画面作成
$ rails g controller Users show

deviseのusersとは別にusers_controller.rbとusers/show.html.erbを生成。

[app/controllers/users_controller.rb]
class UsersController < ApplicationController
  def show
    @user = User.find(params[:id]) #追記
  end
end
%h1 Users#show
%p Find me in app/views/users/show.html.haml
= link_to "編集", edit_user_registration_path

一旦仮で作成

すごく無駄な遠回りをしてしまいました。
ただdeviseについて理解を深めることができた点は良かったと思います。
明日以降、マイページの中身を作成していきます。

個人アプリ開発 コメント機能作成2

コメント投稿フォームの場所を、グループ詳細ページから、コメント作成用ページに変更

後々の仕様を考慮し変更しました
・routes.rb編集
・comments_controller編集
・view comment_new作成

記事詳細ページ view修正

コメントが仮のものだったので、DBから表示するように修正しました。

- @comments.each do |comment|
        - if comment.nil?
          .comment-none
            コメントはまだありません
        - else
          .aquarium-comments__wrapper
            .aquarium-comments__wrapper__user
              .aquarium-comments__wrapper__user__image
              .aquarium-comments__wrapper__user__name
                = comment.user.name
            .aquarium-comments__wrapper__comment
              .aquarium-comments__wrapper__comment__title
                = comment.title
              .aquarium-comments__wrapper__comment__text
                = comment.text
              .aquarium-comments__wrapper__comment--bottom
                .aquarium-comments__wrapper__comment--bottom__rate
                  %p.rate
                    ★★★★☆
                .aquarium-comments__wrapper__comment--bottom__time
                  行った時期:#{comment.visit_date}
                - if comment.user.id == current_user.id
                  .aquarium-comments__wrapper__comment--bottom__edit
                    = link_to "編集", edit_group_comment_path(group_id: @group.id, id: comment.id)
                  .aquarium-comments__wrapper__comment--bottom__delete
                    = link_to "削除", group_comment_path(group_id: @group.id, id: comment.id), method: :delete
  • if comment.nil?

コメントがない場合は”コメントはまだありません”のメッセージを表示

- if comment.user.id == current_user.id
自分のコメントには編集・削除に遷移できるリンクを設置しました。

編集・削除機能の作成

routes.rbの編集
resources :groups do
    resources :comments, only: [:new, :create, :edit, :update, :destroy]
end
コントローラーの編集
[comments_controller]
before_action :set_group

  def new
    @comment = Comment.new
    @comments = @group.comments.includes(:user)
  end
  
  def create
    @comment = Comment.create(comment_params)
    if @comment.save
      redirect_to group_path(@comment.group.id)
    else
      render :new
    end
  end

  def edit
    @comment = Comment.find(params[:id])
  end

  def update
    @comment = Comment.find(params[:id])
    if @comment.update(comment_params)
      redirect_to group_path(@comment.group.id)
    else
      render :edit
    end
  end

  def destroy
    @comment = Comment.find(params[:id])
    @comment.destroy
    redirect_to group_path(@comment.group.id)
  end

  private

  def comment_params
    params.require(:comment).permit(:title, :text, :visit_date).merge(user_id: current_user.id, group_id: params[:group_id])
  end

  def set_group
    @group = Group.find(params[:group_id])
  end
ビューの作成
[comments_edit.html.haml]
= render 'form'

躓き

コントローラーに変数が用意されてないことが原因でエラーを何度も出してしまいました。
ただ慌てずに一つずつ解決することができたと思います。
railsの基本の7つのアクションは何度も学んできてはいましたが、自分でエラーを出しながら考えて実装することで理解が深まっていく気がしました。

今後コメントの新規作成・編集を、オーバーレイとモーダルウィンドウを使用して表示できるように実装していきたいと思います。

→最終的にモーダルウィンドウに
https://qiita.com/takachan_coding/items/9179cf361d0e92ae0bad
http://exrecord.net/how-to-create-overlay-and-modal-window-in-jquery

個人アプリ開発 コメント機能作成

コメント機能を作成しました。

1.モデル作成
[terminal]
$ rails g model comment
2.モデル編集
[comment.rb]
belongs_to :group
belongs_to :user

validates :title, presence: true
validates :text, presence: true

[group.rb  user.rb]
ーーー追記ーーー
has_many :comments
3.migrationファイル編集
class CreateComments < ActiveRecord::Migration[5.0]
  def change
    create_table :comments do |t|
      t.references :group, foreign_key: true
      t.references :user, foreign_key: true
      t.string :title, null: false
      t.text :text, null: false
      t.date :visit_date, null: false
      t.timestamps
    end
  end
end
[terminal]
$ rails db:migrate
4.ルーティング設定
resources :groups do
    resources :comments, only: :create
end
5.controller作成
$ rails g controller comments
6.controller編集
[comments_controller]
def create
    @comment = Comment.create(comment_params)
    if @comment.save
      redirect_to group_path(@comment.group.id)
    end
  end

  private

  def comment_params
    params.require(:comment).permit(:title, :text, :visit_date).merge(user_id: current_user.id, group_id: params[:group_id])
  end

一旦保存できた場合のみ記述

7.view編集
[groups_show.html.haml]
- if current_user
        .aquarium-comments__form
          %h3 口コミの投稿
          .form
            = form_for [@group, @comment] do |f|
              = f.text_field :title, class: 'form__title', placeholder: 'タイトルを入れてください'
              = f.text_area :text, class: 'form__text', placeholder: '口コミ本文を入れてください'
              = f.date_field :visit_date, class: 'form__date'
              = f.submit '投稿', class: 'form__submit'

if corrent_user でログイン時のみフォームを表示

明日以降、編集・削除機能と
保存できなかった場合の処理を作成していきます。

個人アプリ開発 写真投稿機能作成2

作業内容

修正 前回の続き

課題:新規作成ページで画像投稿フォームは複数用意することができたが、写真が1つしか保存されない

フィールドを複数作ればいいのかと思っていましたが、上手くいきませんでした。
上書きされるのか、最後の一つのみ保存される。

[_form.html.haml]
= f.fields_for :images, @group.images.build do |i|
      = i.file_field :image 
      = i.file_field :image
      = i.file_field :image
      = i.file_field :image

▶︎無理やりフィールドだけ並べたことが原因でした。
下記のように編集し、複数画像が無事保存されました。

[_form.html.haml]
= f.fields_for :images do |i|
      = i.file_field :image 
[groups_controller]
def new
    @group = Group.new
    4.times{@group.images.build}
end

newアクション内の@group.images.buildでgroupにネストしたimageを定義しておく。
4.timesとすることでビュー側で画像アップロードのフォームが4つ生成される。

記事詳細表示機能 CSS

ページにスタイルを当てて完了。
メイン画像が粗くなってしまい不安になりましたが、原因としてはケータイ画像だったせいのようです。
元サイズが表示サイズより小さかった。
参考:
HTMLで画像の画質が荒くなる原因と対処法を現役デザイナーが解説【初心者向け】 | TechAcademyマガジン

f:id:kobegoro:20200806082527p:plain