コメント機能を追加するときのポイント

f:id:kokorouruou:20210718183118p:plain

私が作成しているアプリケーション「Yamashiru」を受けて気になった点や復習した方が今後の役に立つと思って作成しています。

さらにエンジニア初心者の方に向けて タメになる情報をお届けします。

今回は、、、

コメント機能を追加するときのポイント

今回のケースは投稿に対してコメント機能を加える際の注意点についてまとめました。

dependent: :destroy について

dependent: :destroyを追加することで、 親モデルを削除する際に、その親モデルに紐づく「子モデル」も一緒に削除できるようになります。 今回の私のケースですと親モデル=投稿機能、子モデル=コメント機能になります。よって投稿が削除されると コメントも削除されるということになります。

tweetモデル

class Tweet < ApplicationRecord
  <中略>

  has_many :comments, dependent: :destroy

commentモデル

class Comment < ApplicationRecord
  <中略>

  belongs_to :tweet

その際にルーティングもネストされているか確認します。

routes.rb

resources :tweets do
    resources :comments, only: :create
end

いかがでしたでしょうか? 1個ずつ落ち着いて実施出来れば簡単な操作になりますので是非ご活用下さい!

DBにデータが登録されない時の対処(エラーが出ない)

f:id:kokorouruou:20210718183118p:plain

私が作成しているアプリケーション「Yamashiru」を受けて気になった点や復習した方が今後の役に立つと思って作成しています。

さらにエンジニア初心者の方に向けて タメになる情報をお届けします。

今回は、、、

DBにデータが登録されない時の対処

今回のケースは今まで画像投稿が出来ていたのに突然DBに保存できなくなってしまった時の対処方法についてまとめました。

問題点を確認

エラーが出ない場合はbinding.pryを活用します。今回のポイントは「tweetで保存(create)しようとしたが出来なかった」です。

Gemfile

gem 'pry-rails'

tweets_controller.rb

def create
    binding.pry   #ここに入れます
    @tweet = Tweet.new(tweet_params)
    if @tweet.save
      redirect_to root_path
    else
      render :new
    end
end

ターミナル

  13: def create
 => 14:   binding.pry
    15:   @tweet = Tweet.new(tweet_params)
    16:   if @tweet.save
    17:     redirect_to root_path
    18:   else
    19:     render :new
    20:   end
    21: end

[1] pry(#<TweetsController>)> params
=> <ActionController::Parameters {"authenticity_token"=>"nHTZ+u5/93ovBjChsu26SBv8hlSqSGJBRBzMzKoscajUOaCI2sikOtszQsGqjSnI0mU4AN2+DDEiJQ+1G9ca2g==", "tweet"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x00007f8487626c78 @tempfile=#<Tempfile:/var/folders/z5/hwd0zxps2ld2xpsfx_6bjb6c0000gn/T/RackMultipart20210729-2283-1c34iv8.jpg>, @original_filename="pexels-dziana-hasanbekava-5589435.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"tweet[image]\"; filename=\"pexels-dziana-hasanbekava-5589435.jpg\"\r\nContent-Type: image/jpeg\r\n">, "title"=>"大パノラマ", "theme_id"=>"4", "prefecture_id"=>"6", "mountain_name_id"=>"4", "climbing_time_id"=>"5", "stamina_id"=>"4", "mountain_view_id"=>"3", "danger_id"=>"2"}, "commit"=>"SEND", "controller"=>"tweets", "action"=>"create"} permitted: false>
[2] pry(#<TweetsController>)> tweet_params
  User Load (0.5ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 ORDER BY `users`.`id` ASC LIMIT 1
  ↳ app/controllers/tweets_controller.rb:34:in `tweet_params'
=> <ActionController::Parameters {"image"=>#<ActionDispatch::Http::UploadedFile:0x00007f8487626c78 @tempfile=#<Tempfile:/var/folders/z5/hwd0zxps2ld2xpsfx_6bjb6c0000gn/T/RackMultipart20210729-2283-1c34iv8.jpg>, @original_filename="pexels-dziana-hasanbekava-5589435.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"tweet[image]\"; filename=\"pexels-dziana-hasanbekava-5589435.jpg\"\r\nContent-Type: image/jpeg\r\n">, "title"=>"大パノラマ", "theme_id"=>"4", "prefecture_id"=>"6", "mountain_name_id"=>"4", "climbing_time_id"=>"5", "mountain_view_id"=>"3", "stamina_id"=>"4", "danger_id"=>"2", "user_id"=>2} permitted: true>

ターミナル

[1] pry(#<TweetsController>)> @tweet.image
=> #<ActiveStorage::Attached::One:0x00007f8483e83aa0
 @name="image",
 @record=
  #<Tweet:0x00007f848780cd58
   id: nil,
   title: "テスト",
   theme_id: 4,
   prefecture_id: 6,
   climbing_time_id: 5,
   mountain_view_id: 3,
   stamina_id: 4,
   danger_id: 2,
   user_id: 2,
   category_id: nil,     #不要なidが含まれていてnilになっている
   created_at: nil,
   updated_at: nil,
   mountain_name_id: 4>>

問題点の対処

別機能を付ける際に後にアソシエーションでcategoryを追加したことによる原因ということが判明しました。では先程のnilはどのように解消すれば宜しいでしょうか。

model/tweet.rb

<中略>
  belongs_to :category, optional: true   #optional: true を追加

optional: trueは、belongs_toの外部キーのnilを許可するというものであり こちらでデータ登録が出来る様になりました。

いかがでしたでしょうか? 1個ずつ落ち着いて実施出来れば簡単な操作になりますので是非ご活用下さい!

カラム追加時のエラー

f:id:kokorouruou:20210718183118p:plain

私が作成しているアプリケーション「Yamashiru」を受けて気になった点や復習した方が今後の役に立つと思って作成しています。

さらにエンジニア初心者の方に向けて タメになる情報をお届けします。

今回は、、、

カラムの追加の際のエラー対処

どうしてもアプリケーションを作っていく中で「こんな機能も入れたいな。」と思ってテーブルを修正される方も多いかと思います!その時に私が遭遇したエラーをご紹介します。

エラー内容

カラムを追加した後にrails db:migrateを実施したところ以下のエラーが発生しました。

-- create_table(:tweets)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Column `user_id` on table `tweets` does not match column `id` on `users`, which has type `bigint(20)`. To resolve this issue, change the type of the `user_id` column on `tweets` to be :bigint. (For example `t.bigint :user_id`).
Original message: Mysql2::Error: Cannot add foreign key constraint

<中略>

エラーとの向き合い方

ポイントはどんな文章が記載されているかを冷静に見極めることです。

気になる文章を翻訳してみます

Column `user_id` on table `tweets` does not match column `id` on `users`, which has type `bigint(20)`. To resolve this issue, change the type of the `user_id` column on `tweets` to be :bigint. (For example `t.bigint :user_id`).
テーブル `tweets` のカラム `user_id` が `users` のカラム `id` と一致しません。この問題を解決するには、`tweets` の `user_id` カラムの型を :bigint に変更します。(例えば `t.bigint :user_id`)。

エラー対処

結論、Railsでは外部キーを使用する際はreferences型を推奨しているので、bigint型を使用する必要はありません。

このエラーのポイントは参照できませんということなので、マイグレーションファイルの作成順に問題があると仮説できます。

f:id:kokorouruou:20210728224856p:plain

添付画像のように数字部分を、参照される側(今回の場合categories)のテーブルよりも外部キーを使用するテーブル(今回の場合tweets)の数字を大きくすれば解決します。 こちらは手入力で変更が可能です。

20210711053719_create_tweets.rb  #20210711(2021/7/11)を20210728(2021/7/28)に変更

その後に通常通りrails db:createを実施したところテーブルの修正が出来ました。

いかがでしたでしょうか? 1個ずつ落ち着いて実施出来れば簡単な操作になりますので是非ご活用下さい!

クラスとインスタンス①

自身が学んできたときになかなか言語化できなかった内容を作成しています。

今回は、、、

クラスとインスタンス

Rubyに用意された値(文字列、数値、ハッシュ、配列など)以外に新しい種類の値を作るために必要な概念です。

データの元となる設計図

値は種類毎に役割や使用できるメソッドが異なり、新しい種類の値を作る際もルールを決めておく必要があります。

クラス

属性と処理(メソッド)のルールを定義する。 (例:車の場合 クラス=ひな形=車の設計図) クラスは、共通の属性と処理を決めるだけで、実態がありません。

クラスの定義方法

class Car  #クラス名は半角英数大文字

end

設計図からデータを作成

クラスから生成される、データを持ったインスタンスを作成します。

インスタンス

クラスを元にして作られるデータです。 (例:車の場合 設計図から作られて実際に販売される車) インスタンスはクラスが使用できるnewメソッドを実行して生成します。

newメソッド

使用したクラスのインスタンスを生成して返します。

newメソッドを使ってインスタンスを生成します。

class Car

end

fire_truck = Car.new   #インスタンスを生成
puts fire_truck   #インスタンスを出力

次回はクラスの中に定義するクラスメソッドとインスタンスメソッドを紹介します。

MVC

f:id:kokorouruou:20210718183118p:plain

私が作成しているアプリケーション「Yamashiru」を受けて気になった点や復習した方が今後の役に立つと思って作成しています。

さらにエンジニア初心者の方に向けて タメになる情報をお届けします。

今回は、、、

MVC

基礎中の基礎ですが、アプリケーションを作成する際に常に頭でイメージしておかないと上手く記述が繋がらず、実装したい機能が反映しないことも多々あります。今のうちに言語化しておきましょう。

MVCの仕組み

MVCとは、プログラミング手法のアプローチの一種でRuby on Railsでも採用されています。 Webアプリケーションを動かすために必要な処理の一部を分類し分けることで、保守性、可読性の高いコードを維持できます。 「V」はViewの略。実際にクライアント側に表示される見た目の部分です。 「M」はModelの略。Webアプリケーションにおけるビジネスロジック(データベースから取得してきた値を加工するメソッドや、レコード検索の条件が書かれたメソッド、データを保存する前に加工するメソッドなど)を定義します。 「C」はControllerの略。クライアントからのリクエストに対して適切なレスポンスを返すことや、そのレスポンスに必要なデータの用意を行う。あくまでも用意するだけが責務なので、データの加工など複雑なロジックはControllerには書きません。

モデルの作成

% rails g model モデル名

テーブルの作成

モデルを生成時に作られるマイグレーションファイルを修正。テーブルに作成するカラムとその型を、changeというメソッドの中で指定します。

<中略>
def change
    create_table :tweets do |t|
      t.string :name
      t.string :text
<中略>

マイグレーションを実行。(=テーブルの作成)

% rails db:migrate

ルーティングを設定

Ruby on Railsには、アクションの設定が慣習的に決められており、下記の表のようなアクションが存在します。

7つのアクション
index         一覧表示
show          詳細表示
new           生成
create        保存
edit          編集
update        更新
destroy       削除

resourcesメソッドを使って7つのアクションへルーティングを自動生成します。

Rails.application.routes.draw do
  resources :tweets
end

コントローラーの作成

% rails g controller コントローラー名

コントローラーを作成するとき、コントローラー名は複数形で命名する。

コントローラーにアクションを定義

class TweetsController < ApplicationController
  def index
    @tweets = Tweet.all
  end
end

一例ですが、こちらはtweetsテーブルのレコードを全て代入しています。

ビューの作成

viewsディレクトリを活用しながら様々なレイアウトを作成することがで出来ます。

いかがでしたでしょうか? 1個ずつ落ち着いて実施出来れば簡単な操作になりますので是非ご活用下さい!

画像投稿

f:id:kokorouruou:20210718183118p:plain

私が作成しているアプリケーション「Yamashiru」を受けて気になった点や復習した方が今後の役に立つと思って作成しています。

さらにエンジニア初心者の方に向けて タメになる情報をお届けします。

今回は、、、

画像投稿について

SNS等でよく使用される画像投稿について、今回はActive Storageというアップロードツールを使用して紹介します。

Active Storageとは

ファイルアップロード機能を簡単に実装できるGemです。指定のコマンドを実行するだけで簡単に導入が出来ます。

画像加工ツールの導入

Active Storageでファイルをアップロードして保存した後、画像を加工してから(サイズや色など)表示できるようにします。

ImageMagick

% brew install imagemagick

MiniMagick

Gemfile

gem 'mini_magick'

ImageProcessing

Gemfile

gem 'image_processing', '~> 1.2'

上記が入力終えたら

% bundle install

Active Storage

% rails active_storage:install

% rails db:migrate

画像の保存

先ほど作成したActive Storageのテーブルに、画像を保存するための実装を行います。

has_one_attached

各レコードとファイルを1対1の関係で紐づけるメソッド。

使い方イメージ

class モデル < ApplicationRecord
  has_one_attached :ファイル名
end

Tweetsテーブルで投稿する場合

class Tweet < ApplicationRecord
  belongs_to :user
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :theme
  belongs_to :prefecture
  belongs_to :mountain_name
  belongs_to :climbing_time
  belongs_to :mountain_view
  belongs_to :stamina
  belongs_to :danger


  has_one_attached :image

  validates :title, :image, presence: true
  with_options numericality: { other_than: 1, message: "can't be blank"} do
  validates :theme_id
  validates :prefecture_id
  end
end

アソシエーションが組めた後は画像の保存を許可するストロングパラメーターをcontrollerに記述

  private

  def tweet_params
    params.require(:tweet).permit(:title, :image, :theme_id, :prefecture_id, :mountain_name_id, :climbing_time_id, :mountain_view_id, :stamina_id, :danger_id).merge(user_id: current_user.id)
  end

画像の表示

保存した画像をブラウザ上で表示させるために今回はRailsのヘルパーメソッドであるimage_tagを使用して、簡単に画像を参照します。

image_tag

img要素を生成するRailsのヘルパーメソッドです。

使い方イメージ

# ファイルをモデルから指定する場合
<%= image_tag モデル.画像ファイル %>
<%= image_tag user.avatar %>

# app/assets/ディレクトリ下の画像ファイルパスでも指定できる
<%= image_tag 画像ファイルのパス %>
<%= image_tag "avatar.png" %>

いかがでしたでしょうか? 1個ずつ落ち着いて実施出来れば簡単な操作になりますので是非ご活用下さい!

削除関連

f:id:kokorouruou:20210718183118p:plain

私が作成しているアプリケーション「Yamashiru」を受けて気になった点や復習した方が今後の役に立つと思って作成しています。

さらにエンジニア初心者の方に向けて タメになる情報をお届けします。

今回は、、、

削除関連まとめ

モデルやテーブル、データベースなど生成してみたけど「あ、間違えてる」ってこと多々ありませんか?そんな時に「削除コマンドはなんとなく知ってるけど、押したらどうなってしまうんだろう、、、」や「コマンドで削除したり、手動で削除したりややこしい」と不安になる方も多いかと思います。そういった内容も詳しく書いていこうと思います!

データベースの削除

% rails db:drop

rails db:createで作成した際に削除するコマンドになります。

データベースの削除とマイグレーションファイルの適用を一括登録

% rails db:migrate:reset

データベースの設定は間違っていないものの、再度データベースを作り直し、既存のマイグレーションファイルを適用したい場合にとても有効なコマンドです。実際にどのような操作が行われるのか。

  1. データベースを削除する

  2. データベースを再度生成する

  3. 既存のマイグレーションファイルをすべて適用する

*データベースを一度削除するため、保存されているデータなどはすべて削除されます。

コントローラーの削除

% rails d controller コントローラー名

rails g controllerで作成した際に削除するコマンドになります。

モデルの削除

% rails d model モデル名 rails g modelで作成した際に削除するコマンドになります。

カラムの修正

*前提として適用済みのマイグレーションファイルを編集してはいけません。

% rails db:migrate:status #マイグレーションファイルが実行済みか確認(up、downの確認)

% rails db:rollback #マイグレーションファイルを差し戻す *削除の場合はdownした状態で右クリック▶︎削除で手動で実施

% rails db:migrate #マイグレーションファイルのカラム名などを修正してから実行

いかがでしたでしょうか? 1個ずつ落ち着いて実施出来れば簡単な操作になりますので是非ご活用下さい!