Sochi419のブログ

プログラミング初学者です。Ruby, JavaScriptを学習中です。猫が好きです。フィヨルドブートキャンプというスクールの受講生です。

自作サービス案 没ネタ集

はじめに

こんにちは! フィヨルドブートキャンプというプログラミングスクールで学習をしているSochiと申します。

スクールの最終課題に「自作サービスを作る」というものがあるのですが、ようやく自作サービス案が決まったので、今まで考えたサービス案の没ネタを投稿しようと思います。

個人的にアイデアを考えるのが好きで思いつくたびにメモしていたのですが、大量にたまってきたので忘備録も兼ねて、ブログにまとめてみようと思いました。 ちなみに、絶対使わないだろっていう案や、くだらない案もあるのですが、一応文書として残しておこうと思いました。

※ 技術記事ではないので消すかもしれません。

※ そのサービス案が技術的に実現可能かどうかや、上位互換の競合がいるかどうかは考慮しておりません。

サービス案

1. プログラミング学習関連

オンライン競プロバトル

マッチングした相手と、競プロでリアルタイムで早く解いた方が勝ち。

メソッドかるた

  • プログラミング言語のメソッドに関するかるたを、オンライン上で複数人で遊べる。
  • 以前、rubyメソッドかるたというワードを耳にしたので、オンライン上でできたらなと思った。
    メソッドかるた [メソッドかるた] というサービスは、 [オンラインでプログラミング言語のメソッドかるたを遊びたい] [プログラミング関連の学習者やイベント参加者] 向けの、 [パーティーゲーム]です。 ユーザーは [ブラウザ上で、お題の答えの札をカーソルで選択すること] ができ、 [かるたオンライン] とは違って、 [複数人で遊べて、みんなのカーソルが常に表示されているので、回答に迷っている様子がリアルタイムで見れる機能] が備わっている事が特徴です。

苦しみを吐露する掲示

  • 苦しみを吐露するとスッキリした経験がある。匿名で今自分が悩んでいることや苦しんでいることを吐露できるサービス。それをみたユーザーはポジティブなスタンプを押してリアクションできる。

2. Discord関連

discordフォローユーザータイムライン機能

  • discord で、自分のフォローしたユーザーのみ twitter のタイムラインのように時間順に見れる機能。
  • discordで個人チャンネルを一つ一つ回るのが面倒。投稿の通知をオンにするのもなんか違うなと思う人向け。

雑談話題提供サービス

  • 輪読会などの集まりで冒頭の 5 分とかで話題がない時に、話題を提供してくれるサービス
  • discord 通話に入っている人の直近の呟きで、話題になり得そうな単語を抽出して提案してくれる。
  • discord 通話に入っている全員のプロフィールから、共通の趣味を抽出して提案してくれる。

雑談話題提供サービス [雑談話題提供サービス] というサービスは、 [Discord のボイスチャンネルで、雑談の話題を提供してくれる] [Discord サーバーにいる人] 向けの、 [雑談ネタ提供サービス]です。 ユーザーは [discord のボイスチャンネルにいる人の最近の言動、共通の趣味、今やっているプラクティスを知ること] ができ、 [既存の雑談鉄板ネタツールのような、鉄板の話題を提案したり、ルーレットで話題を提供するの] とは違って、 [通話内にいる人の共通点や最近の言動を抽出して、参加者にホットな話題を提供してくれる機能] が備わっている事が特徴です。

discord で匿名ユーザとしてしか入室できないチャンネル。

  • 全体チャンネルとかだと発言しづらいし、匿名ユーザ同士だと気軽にチャットできるから。名前は隠される。匿名なので頓珍漢な質問をしても恥ずかしい思いをしないし、変な回答をしてしまっても匿名なので問題なし。

3. 趣味(ネタ)

人狼メモサービス

  • 人狼で一人一人の言動や占い結果をまとめられるサービス
  • 最近、なぜか人狼にハマっているのだが、一人一人の言動などをメモしたり、占い結果などをまとめられる便利なツールがなさそうだったので。

ジョジョのセリフ風でしか発言ができない掲示板。

  • ジョジョ好きが集まる掲示板。 ジョジョのセリフ風な話し方ができない人は管理者の独断によって追放される。ちなみに bot が自動でジョジョ関連の議題を作成して、ユーザーがそれについて語る。

マイナーおすすめ無料漫画紹介アプリ

  • 無料しか紹介できない。ユーザーが無料漫画のURL を貼る。評価数によってみんなの面白い無料漫画が検索上位になるようになる。ワンピースとかそのくらいメジャーな漫画は絶対上位に来てしまうので、メジャーな漫画を紹介した発言は追放される。みんなでマイナーだけど面白い漫画を共有したい人向け。

ドライブコース作成アプリ

  • マップ上でドライブコースをマッピングする。本来のGoogleマップでは目的地を設定してルートが決定されるが、目的地ではなくドライブしたい道路でルートを決められる機能。海沿いや、景観の良い道路を走りたいのに、勝手に最短ルートをgoogle mapが通らせようとするため。

海外旅行やらかし掲示

  • 自分が海外でやらかした経験をシェアできるサービス。知見にもなるし面白そう。私はフィリピンでトランプ詐欺に遭ったりマレーシアで食中毒になったので、同じ轍を踏まないように共有したい。他人のやらかし話は好きなので聞いてみたい。

旅費計算サービス(バックパッカー)

  • 目的地が一つではなく、複数で周遊する場合にどのくらいの費用がかかりそうかの計算が楽になるバックパッカー向けサービス。実際に東南アジア周遊した時や、車中泊で日本周遊をしていたときに、どのくらいの費用がかかるか計算する簡単なサービスが欲しいと思った。

車中泊できる場所マップ

  • 近場で車中泊できる場所を登録できるサービス。

航空券値下げ通知機能

  • 航空券が〇〇円以下になったらメールで告知するサービス。現状の航空券比較サイトは、そのサイト上で値段を調べた瞬間の時刻の値段が表示されるので、時間によって価格が変動しているのに対応できていないと思った。

コラ画像保存サービス

  • コラ画像を保存しておいて、Lineやdiscordの返信時にすぐさま貼るために保存しておけるサービス。たまにコラ画像で適当に返信したいなと思う時がある。保存したコラ画像はタグで種類ごとに検索可能。

強制目覚まし機能

  • 起きたら習慣化したいことを 1分間作業しないとアラームが止まらない。

ディベート対決サービス

  • 希望者はお題を決めて部屋を作り、対戦者を待つ。議題に対してコメントで議論をしていく。第三者がスタンプを押して、客観的にどちらが優勢かをリアクションできる。たまに自分の好きな趣味の話で討論したいなと思う時がたまにある。

信号が少ない道を検索するアプリ

  • ドライブする時に、信号でいちいち止まりたくない人向け。

ドラクエのボスの戦闘再現

  • RPGの戦闘をweb上で再現できるサービス。装備とか覚えている特技とかステータスを自分で設定できる。昔やってたドラクエのラスボス戦をweb上でやりたくなった。

4. 英語学習関係

好きな映画ドラマアニメの英語のセリフを保存しておく機能

印象に残るようなセリフだったら、英語覚えるのが簡単そう。最近、「日本の作品を見る外国人」のリアクション動画を見るのにハマっているので。

英語学習中の日本人と日本語学習中の外国人とマッチングさせる機能。

win-winな関係だからいいのかも。

vtuberの皮を被ってオンライン英会話。

いきなり顔出しはハードル高い人向け。皮はあらかじめ何種類か用意されている。

5. その他

サービス案投稿サービス

イデアを考えるのは割と好きな方で、思いつくたびに案をメモしていたが、大量に案がたまってきたので、整理できたらなあと思った。また、考えた案に対して、どの案が第三者から見て需要があるのか気になった。

エレベーターピッチ [1. サービス案投稿サービス(仮)] というサービスは、 [2. 自分の考えたサービス案が他者にとって需要があるかどうか] を解決したい [3. 個人開発のサービス案を考えている人] 向けの、 [4. サービス案投稿サービス]です。 ユーザーは [5. サービス案を保存できるだけでなく投稿することで、投稿に対して他者からいいねされること] ができ、 [6. クラウドワークスwebアイデア募集ページ] とは違って、 [7. サービス案に対して一般ユーザーからいいねされるので、いいねの数に応じて需要があるのかを客観的に知ることができます。また、サービス案をタグ付きで保存/整理ができるので、このサービスを使う人が自分一人でも活用できること] が備わっている事が特徴です。

色々ランキング

  • 例えば、フィヨルドブートキャンプでどのプラクティスが一番難しいかとか、どこ出身が一番多いかとかランキングできる機能。

輪読会興味ある人マッチング機能

  • こういう本を読もうと思ってます。と投稿して、どのくらいの参加者が見込めそうか、予想できるサービス。もしくはその本に興味がある人同士をマッチングさせる機能。

行きたいとこ保存アプリ

  • google map に目的地を保存をした場合は、現状「行ってみたい」や「旅行プラン」などでフラグを立てることができるが、優先度 「高」「中」「低」 で保存可能な上、 タグで検索可能。(世界遺産/ グルメ/ 滝 などのジャンル分け可)

欲しいものリストを用意して、amazon で値下げした時に通知する機能

amazonでいつどの商品が安くなっているか把握できていないので

ブックマークタグ検索機能

  • ブックマークを保存するときに、① URL, ② タグ を保存することができるサービス。例えば、「SSH の課題の時、どんなサイトを参考にしたっけ。。?」となった時に、保存しておいた大量のブックマークの中からタグで絞り込むことで、関連するブックマークを検索できる。

雑学保存帳

  • 雑談などで貼ってくれたリンクを保存しておくサービス。たまに見返したくなるんだけど、どこで誰がしゃべったか思い出せなくて探せない時がある。

誰かに学習を監視してもらう機能。

通りすがりのユーザにいいねを押してもらえる。本気で集中したい人は、カメラオンで。

気になっている会社の、会社情報を問題形式で出してくれる web アプリ。

面接対策。

電子書籍文章読み上げアプリ

  • 通勤中などパソコンを開けない場所で、電子書籍を読み上げてくれるサービスがあったらいいな。「読む」のではなく「聴く」ことで書籍の理解を深める。運転中や満員電車などの、手を離すことができないので読むことはできないけど、耳が自由な状況で欲しいなと思った。

電車路線図可視化サービス

  • 電車の乗り換え時刻検索時に、map上でどういうルートを通るのか見ることができる機能。駅名とか何線がどこを通っているのか、いまだに全然分かっていないので、路線について詳しくなりたいので。

ガソリン価格をマップ上で表示してくれるサービス

  • ガソリンスタンドのマッピングは既にあるが、なるべく安い料金のガソスタを利用したいため。

おわりに

今後もある程度ネタが貯まれば投稿するかもしれません。 (技術ネタではないので消すかもしれませんが。)

チーム開発の振り返り

これは「フィヨルドブートキャンプ Advent Calendar 2023」の5日目の記事です。 昨日のエントリーは、LEFさんの「世界一わかりやすいWebSocketのサンプルコード(とその解説)」でした!

はじめに

 私の所属しているフィヨルドブートキャンプでは「システム開発」というプラクティスが用意されています。 5月末 ~ システム開発のプラクティスに入り、もうすぐ終わりが見えてきたので、振り返りを書こうと思います。

今回は以下のことについて書こうと思います。

システム開発とは?

 入会して間もない方は「システム開発」という言葉を聞いても分からないかもしれません。 「システム開発」って何!?という話なのですが、仕事と同じ様な形でチームでフィヨルドブートキャンプのアプリを受講生の手で改善していくプラクティスです。用意されたissueに対してポイントが設定されており、合計20ポイント分のissueを消化するとプラクティス終了となります。(私は今、17ポイントを消化して、最後のissueに取り組んでいる段階となります。) プラクティス名は「システム開発」ですが、「チーム開発」と呼ばれることの方が多いです。

システム開発に入る前後の心境

システム開発に入る前の心境

 正直、チームメンバーのレベルについていけるか心配でした。というのも私は過去のプラクティスの進度は早い方ではなく、プラクティスの提出物について、メンターからのレビューの数が他の受講生に比べて多いと感じていました。 また、今までのプラクティスは合格こそしたものの理解できているか自信があまりなく、昔やったプラクティスの内容をほぼ忘れかけていたためです。

システム開発終盤に来ての心境

 意外となんとかなる、というのが正直な感想です。というのもシステム開発の最初に行う作業は「good first issue」と呼ばれる、すごく簡単なもので、例えばUI上の文字を一部分訂正するだけ、のようなものです。そのため、最初に苦戦することはgit操作だと個人的に感じています。最初こそgithubの使い方に慣れが必要なものの、わからないことはすぐに質問をして解消をしていました。特に月水金の16時からやっている質問タイムで主に疑問の解消をしていました。テキストでの質問は、回答をいただけるまでのタイムラグが生じてしまうのに加えて、口頭で説明するよりも難しいため、主に口頭で質問をして疑問の解決をする、という場面が多かったです。途中で難しいissueを抱えてモチベーションが上がらない期間もありましたが、今もなんとかやっていけています。

システム開発で学んだこと

先人が実装した過去のPRは、自分のPRを実装するときの助けになる。

 実際に難しいissueを振られると、手も足も出ず「どうしたらいいの?」と頭を抱えて悩むときがありました。そんな時に役に立ったのが、過去に似たような実装をしているパターンがあります。例えば簡単な例を出すと、「お知らせページでは管理者かメンターしか編集できないようにする。」という機能を実装したい場合に、過去の他のPRで「質問ページでは質問者しか編集することができないようにする」というissueがあったとします。そのissueを眺めれば、「〇〇しか〇〇できない」という実装はどうやっているのか、知ることができます。上記は簡単な例ですが、過去のPRを見ることは自分の実装の助けにもなる場合があるし、何より他人の実装を眺めているだけで勉強になったりします。

仕事に対するイメージがついた

 システム開発のプラクティスに入るまで、仕事では実際にどんなことをやるのか、まっっっっったくイメージが湧きませんでした。システム開発を通して、実際の仕事でもこういう感じで実装していくのかというイメージを持つことができました。また、今までのプラクティスでは個人で進めていきますが、チームで開発していくことを経験することができました。

testを書けるようになってきた。

 システム開発のプラクティスに入ると、「ミニテスト」を書くケースが増えると思います。一応プラクティスで「ミニテスト」について学ぶのですが、プラクティスを終えても、私は理解した自信がありませんでした。しかし、システム開発に入るとミニテストについて嫌でも書くことになります。初めのうちはテストについてどう書けば良いか苦戦しましたが、システム開発ではたくさんのミニテストのサンプルがあるので、見て学ぶことができます。いろんなテストを書く場面に遭遇してテストを書く練習をすることが、テストを書くことができるようになる近道だなと思いました。

失敗したこと

相手との認識合わせの明確化

 issueを振られた時に、相手がどういう実装を望んでいるかについて認識合わせを明確化しないと、二度手間になりまた実装することになります。僕は失敗しました。実際に実装が完了して、「レビューお願いします!」と意気込んでも、確認者から「私が思っていた実装と違うんだけど。」と言われ、再度実装をする、というケースがありました。 まだ練習の段階だから許されますが、実際の仕事となると「納期」があると思うので、実装前の認識合わせはきちんと行いたいなと教訓になりました。

レビュー

 「システム開発」ももうすぐ終わりますが、いまだに他人のレビューを見ることは苦手です。私が他のチームメンバーにレビュー依頼をした時は、的確なアドバイスを頂けるが、私がレビューする立場となると、アドバイスが思い浮かばないケースが多々あり、アドバイスを捻り出すのに時間を費やしてしまう時がありました。「そもそも初学者なんだから、アドバイスが思い浮かばないのは当たり前」と、以前メンターさんに相談した時にアドバイスをいただきました。レビューはコミュニケーションという意味合いもあるので、アドバイスをするだけではなく、こちらから質問をしてみたり、実装について自分の知見になった場合は褒めたりお礼を言ったり、アドバイスをするだけではない、ということを学びました。

おわりに

 長々と書きましたが最後に感想を書くと、システム開発が他のプラクティスに比べて一番成長している実感があります。そもそも今までのプラクティスの内容を総動員して取り組むことになるので、今までのプラクティスの復習になります。また、卒業生が「実際に仕事をしてみて、システム開発でやったことと仕事でやることは似ている」と良く聞くので、システム開発を乗り越えることができれば、仕事でも最低限やっていけるかなという自信に繋がる気がします。ここまで、システム開発を終えた人みたいな感じでつらつらと書いていますが、まだ最後のissueが残っているので、全力で取り組みたいと思います!

testの書き方

プログラミング初学者の私なりに、railsのtestの書き方をまとめてみました。

各テストファイルの役割

├── test・・・Rails標準の各種テスト用のコードファイルやフィクスチャ(テストデータ)などを管理する
│   ├── application_system_test_case.rb
│   ├── channels
│   │   └── application_cable
│   │       └── connection_test.rb
│   ├── controllers・・・コントローラーテスト(機能テスト)のコードファイルを保存する
│   ├── fixtures・・・テスト実行時に最初にロードされるテスト用のデータファイル(YAML形式)を保存する
│   │   ├── books.yml
│   │   ├── comments.yml
│   │   ├── files・・・画像ファイルなどのファイルデータを配置する
│   │   ├── relationships.yml
│   │   ├── reports.yml
│   │   └── users.yml
│   ├── helpers
│   ├── integration
│   ├── mailers
│   ├── models・・・モデル単体のテストのコードファイルを保存する
│   │   ├── book_test.rb
│   │   ├── comment_test.rb
│   │   ├── relationship_test.rb
│   │   ├── report_test.rb
│   │   └── user_test.rb
│   ├── system・・・UIの操作を活用したシステムテストのコードを保存する。Capybaraを使用
│   │   └── books_test.rb
│   └── test_helper.rb・・・全テストファイルにrequireすることで、共通のテスト条件として組み込まれる

基本いじるのは、下記の3つの印象。

  1. fixtures→テスト時に使用するデータファイルがある。
  2. models→モデルテスト
  3. system→システムテスト

fixturesファイルについて

  • 初期状態

scaffoldで用意された初期状態は以下のような感じ。

one:
  title: MyString
  memo: MyText

もし、テスト時に使用しないのであれば、全てコメントアウトする。 使う場合は以下のような感じにする。

  • 例 test/fixtures/users.yml
Alice:
  name: Alice
  email: alice@example.com
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>

上記のように定義しておけば、テストメソッドで、hoge = users(:Alice)のようにすれば呼び出せる。 ちなみに、fixturesで定義しなくても、各メソッドで定義しても使える。

hoge = User.new(email: 'foo@example.com', name: '')

メソッドが何個もあるなら、いちいち定義するのが冗長なので、fixtureにデータを書いておくのが吉。

modelテストについて

modelテストには、modelで定義したメソッドを定義する。

例えばuserモデルに以下のメソッド定義がある場合、

  • app/models/user.rb
  def name_or_email
    name.presence || email
  end

対応するuserモデルテストは以下のように書く。

  • test/models/user_test.rb
  test '#name_or_email' do
    user = User.new(email: 'foo@example.com', name: '')

    assert_equal 'foo@example.com', user.name_or_email
  end

assertを使って、期待される結果が返ってくるかをテストする。

assert_equal '期待される返り値', 実際の返り値
  • よく使いそうなassertメソッド
メソッド 役割
assert_empty 指定された項目が空であるかを確認する
assert_equal 相互に指定された内容が一致するかを確認する
assert_difference ブロックの評価結果の差分を確認する

他にもassertメソッドは何個かあるみたい。 https://railsguides.jp/testing.html#%E5%88%A9%E7%94%A8%E5%8F%AF%E8%83%BD%E3%81%AA%E3%82%A2%E3%82%B5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3

systemテストについて

systemテストではrailsCRUD機能をテストする。 scaffoldした時点で、CRUDテストの雛形は作成されている。 rails test:systemをして、エラーを解消しながら、テストを書く流れとなる。

下記に、自作したテストファイルを記載する。今後テストするときは、下記のお手本を参考にテストを書くといいかもしれない。

booksのCRUDをテストする場合

require 'application_system_test_case'

class BooksTest < ApplicationSystemTestCase
  setup do
    visit root_url
    fill_in 'Eメール', with: 'alice@example.com'
    fill_in 'パスワード', with: 'password'
    click_button 'ログイン'
  end

  test 'visiting the index' do
    visit books_url
    assert_selector 'h1', text: '本'
  end

  test 'creating a Book' do
    visit books_url
    click_on '新規作成'

    fill_in 'タイトル', with: 'Ruby超入門'
    fill_in 'メモ', with: 'すごくわかりやすい!!'
    fill_in '著者', with: 'igaiga'
    click_on '登録する'

    assert_text '本が作成されました。'
    assert_text 'Ruby超入門'
    assert_text 'すごくわかりやすい!!'
    assert_text 'igaiga'
  end

  test 'updating a Book' do
    visit books_url
    click_on '編集'

    fill_in 'タイトル', with: '独習RubyonRails'
    fill_in 'メモ', with: 'わかりやすい!!'
    fill_in '著者', with: '小餅良介'
    click_on '更新'

    assert_text '本が更新されました。'
    assert_text '独習RubyonRails'
    assert_text 'わかりやすい!!'
    assert_text '小餅良介'
  end

  test 'destroying a Book' do
    visit books_url
    page.accept_confirm do
      click_on '削除'
    end

    assert_text '本が削除されました。'
  end
end

rails基本操作まとめ

rails基本操作まとめ

プログラミング初学者の私が、初学者目線でrailsの基本操作についてまとめました。

ページを作成

rails generate controller welcome index

image.png

welcomeという名前のページが作成された。

作成ページをトップページにする

config/routes.rbに、root 'welcome#index'を記述する

Rails.application.routes.draw do
  get 'welcome/index'

  resources :articles
  root 'welcome#index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

リンクを貼る

<%= link_to 'Show list', articles_path %>

基本的な書き方は以下。

link_to 'リンク文字列', リンク先のパス(URL)

ルーティングの名前でリンク先を指定する

こちらが最も一般的で基本的な使い方で、同じアプリケーション内へのリンクを作成する場合はこちらを使う。

ルーティングの名前を確認するrake routesコマンドを実行。

rake routes

image.png

赤い枠で囲った部分がルーティングの名前。 例えば、users_controllerのnewアクション(新規作成画面)にリンクを貼りたいときは

<%= link_to '新規作成’, new_user_path %>

と書く。

外部のURLやパスを指定する場合

外部のサイトのURLや同じアプリケーション内のパスを指定するときは次のように書く。

<%= link_to 'Yahoo', 'http://www.yahoo.co.jp/' %>
<%= link_to 'ユーザー一覧’, ‘/users/index’ %>

リンク先のパスに、URLやアクションをそのまま記述する。

カラムを追加する手順

MVC(model, views, controller)を順に修正する必要がある。

①modelの変更

データベースを含めてモデルを変更するには、以下のコマンドを実行

rails generate migration AddNameToArticle name:string

書式は以下。

rails generate migration Addカラム名Toディレクトリ名 name:string

以下で、データベースに反映させる。

rails db:migrate

②viewsの変更

次に見た目の変更をする。 viewsではすでにあるカラムに倣って、追記すればOK

例えば元々contentカラムがあって、nameカラムを追加したい場合は viewsファイル内で、 <td><%= article.content %></td> <td><%= article.content %></td> <td><%= article.name %></td> のように新規カラムを、元あるカラムの記述に倣って追記する。

③controllerの変更

controllerを変更しないと、新規で追加したカラムの内容を新規作成や修正をしても、内容をモデルに書き込んでいないので、反映されない。(グローバル変数 @hoge に関連づけられていない) そのためcontrollerを修正する。

controllerファイルの一番下の方に、モデルについての記述がある。 def article_params params.require(:article).permit(:content) end

もしnameカラムを今回追加したなら、下記のようにnameの記述を追記する。 def article_params params.require(:article).permit(:content, :name) end

一度にmvcを修正すると、間違っていたとき誤り箇所を見つけるのが大変だから、 viewsまで修正したら一度、修正内容が反映されているか、確認したほうが良いと思う。

rails console

rubyのコマンドをそのまま実行できる

rails c
irb(main):001:0> p "hello world"
"hello world"
=> "hello world"
irb(main):002:0>

rails cを使えば、ブラウザ上でデータを追加しなくても、ターミナル上で追加できたりする。 例えばデータベースの内容を書き換える場合は、以下のようにする

irb(main):005:0> article = Article.find(2) # articleにidが2に該当するデータを代入
irb(main):006:0> article.content
=> "hello world" # contentキーに該当する部分
irb(main):007:0> article.content = "hello console" # contentキーの該当部分を変更
irb(main):008:0> article.save # 変更内容を保存する。
irb(main):009:0> article.content
=> "hello console" # 変更されたことを確認。

ちなみにallメソッドで、データベースの全データを見れる。

 irb(main):007:0> articles = Article.all
 irb(main):007:0> articles.each {|article| p article}

  Diary Load (0.3ms)  SELECT "diaries".* FROM "diaries"
=> #<ActiveRecord::Relation [#<Diary id: 1, content: "hello world", created_at: "2022-10-26 00:00:00", updated_at: "2022-10-26 00:00:00", name: "gino">, #<Diary id: 2, content: "hello ruby", created_at: "2022-10-26 00:00:00", updated_at: "2022-10-26 00:00:00", name: "paiza">, #<Diary id: 3, content: "hello rails", created_at: "2022-10-26 00:00:00", updated_at:"2022-10-26 00:00:00", name: "gino">]>

ちなみに、controllerファイルの@articlesは、ハッシュの形で全データを取り出している。

 def index
    @articles = Article.all
 end

ActiveRecord

image.png

ルーターの設定

rails routesコマンドで、ルーターの設定を確認できる。 ルーターとはRails アプリへのアクセスを振り分けること。

       Prefix Verb   URI Pattern                  Controller#Action
welcome_index GET    /welcome/index(.:format)     welcome#index
     articles GET    /articles(.:format)          articles#index
              POST   /articles(.:format)          articles#create
  new_article GET    /articles/new(.:format)      articles#new
 edit_article GET    /articles/:id/edit(.:format) articles#edit
      article GET    /articles/:id(.:format)      articles#show
              PATCH  /articles/:id(.:format)      articles#update
              PUT    /articles/:id(.:format)      articles#update
              DELETE /articles/:id(.:format)      articles#destroy
         root GET    /                            welcome#index
  • routes.rb このファイルを設定することで、ルーターの設定を修正できる。
Rails.application.routes.draw do
# welcome/indexにアクセスしたとき同じ名前のコントローラのindexにアクセスするという設定。
  get 'welcome/index' 

# resoucesは、articlesコントローラに対する設定を自動生成する。(routes.rbが作成されたときに勝手に作られる。)
  resources :articles

# URLに何もつけずにリクエストしたとき、rootで記述したコントローラが呼び出される。
  root 'welcome#index'
end

コントローラファイルの記述

自動生成されたcontrollerファイルは、下記のshowアクションのように何も記述がされていないにも関わらず、showアクションが実行できるのは何故だろうか。

class ArticlesController < ApplicationController
  before_action :set_article, only: [:show, :edit, :update, :destroy]

  def index
    @articles = Article.all
  end

  def show
  end

実は2行目のbefore_actionで各アクションの前に自動で実行するプログラムが記述されている。このbefore_actionの設定はコントローラファイルの下の方にあるprivateに記述されている。

 private
    def set_article
      @article = Article.find(params[:id])
    end
end

つまり、特定のidに合致するものが@articleに格納されている。params[:id]にはwebブラウザから送信されたパラメータが格納されている。

ヘルパーメソッドの解説

ヘルパーメソッドとは

ヘルパーメソッドは下記のようなリンクについての記述のこと

<%= link_to 'Edit', edit_article_path(@article) %> |
<%= link_to 'Back', articles_path %>

ヘルパーメソッドのpathの指定方法

rails routesでpathで指定できるもの一覧が表示できる。 Prefixカラムに記載されているものが、pathとして利用できる。

image.png

例えば、articleというpathが用意されているので、下記のようなpathの書き方ができる。

<%= link_to 'Back', article_path %>

検索フォームの追加

検索した用語にヒットするデータのみを絞り出す機能を追加したい。

image.png

手順1. viewsに検索フォームを追加する

<%= form_tag('/articles', method: 'get') do %>
<%= label_tag(:name_key, 'Search name:') %>
<%= text_field_tag(:name_key) %>
<%= submit_tag('Search') %> <%= link_to 'Clear', articles_path %>
<% end %>

手順2. コントローラのindexメソッドに検索コードを追加する

def index
  if params[:name_key]
    @articles = Article.where('name LIKE ?', "%#{params[:name_key]}%")
  else
    @articles = Article.all
  end
end

作成したrailsアプリ2つを関連づける

関連づけるとは、バラバラに作成されたページ同士を関連づけること。 例として、カテゴリリストとお店リストを作成して、関連づける。

手順1. 関連づけるリスト2つをscaffoldで作成する。

rails generate scaffold category name:string
rails db:migrate

image.png

rails generate scaffold shop category_id:integer name:string address:string
rails db:migrate

手順2. viewsファイルでそれぞれのリストに行き来できるリンクを貼る

  • app/views/categories/index.html.erb
 <%= link_to 'Show Categories', categories_path %>

image.png

  • app/views/shops/index.html.erb
<%= link_to 'Show Shops', shops_path %>

image.png

カテゴリ名にidが入ってしまっているので、ここを直していく。

手順3. modelに入れ子(親子)関係の記述を行う

親の場合。

  • app/models/category.rb
class Category < ApplicationRecord
  has_many :shops
end

子の場合

app/models/shop.rb
class Shop < ApplicationRecord
  belongs_to :category
end

手順4. 登録時にカテゴリを選択できるようにする

登録・修正フォームで、カテゴリを選択できるようにするには、次のように記述する。 (子のviewsの方で、登録時に親のどのidに関係するかを選択できるようにする) - app/views/shops/_form.html.erb

<div class="field">
  <%= f.label :category_id %>
  <%= f.select :category_id, Category.all.map{|o| [o.name, o.id]} %>
</div>

これで、登録時にカテゴリを選べるようになった。 image.png

google mapを組み込んでみる。

  • API Application Program Interfaceの略。別のプログラムを呼び出すために用意された、命令や関数のことを指す。

  • app/views/shops/show.html.erb

基本的にはviewsファイルにリンクを貼るだけで使用できる。 使用するにはAPIキーを取得する必要がある。

<%= content_tag(:iframe, 'map', src:'https://www.google.com/maps/embed/v1/place?key=AIzaSyCJBgcuCowQa5-V8owXaUCHhUNBN8bfMfU&q=' + @shop.address, width: 800, height: 400, frameborder: 0) %>

<br>

例. googleAPIキー取得手順。 1. Google Developers Consoleにアクセスする

Google Developers Console https://console.developers.google.com/

  1. プロジェクトを作成を選択
  2. Google APIが表示されたら、Google Maps APIから「Google Maps Embed API」を選択
  3. 「有効にする」をクリック
  4. 「認証情報を作成」をクリックして、「必要な認証情報」ボタンをクリック
  5. 表示されたAPIキーを記録する

devise導入手順

手順1. インストール

まずはgemをインストール。

gem 'devise'

その後deviseをインストール。

rails g devise:install

手順2. デフォルトURLを追加する

  • config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

を追記。(追記箇所はRails.application.configure do~endの中ならどこでも)

手順3. root_urlを指定する

config/routes.rb

root 'welcome#index'

手順4. フラッシュメーセージの表示場所を作る

app/views/layouts/application.html.erb body部を下記に変更

<body>
  <p class="notice"><%= notice %></p>
  <p class="alert"><%= alert %></p>
  <%= yield %>
</body>

手順5. ユーザ認証用のviewを生成する

rails g devise:views

このコマンドで、viewsのしたにdeviseディレクトリが生成される。

  • ログイン: app/views/devise/sessions/new.html.erb
  • サインアップ: app/views/devise/registrations/new.html.erb
  • ユーザ情報変更: app/views/devise/registrations/edit.html.erb
  • パスワード変更: app/views/devise/passwords/edit.html.erb
  • メール認証: app/views/devise/confirmations/new.html.erb
  • パスワードリセット: app/views/devise/passwords/new.html.erb
  • アカウントアンロック: app/views/devise/unlocks/new.html.erb

deviseにユーザ認証用のUserモデルを作成する。

ログインするユーザを管理するため、userモデルが必要になる。

手順1. userモデルを作成する。

rails g devise User
$ rails db:migrate

手順2. deviseに初期ユーザを一括登録(ユーザの初期登録が必要ならば)

db/seeds.rb

下記のような書式で記載する。何人分書いてもok

User.create(email: 'admin@gmail.com', password: 'password')
User.create(email: 'kirishima@gmail.com', password: 'password')

ちなみにUserはモデル名なので、モデル名によって書き換える。 モデル名.create(email: 'admin@gmail.com', password: 'password') その後、下記コマンドで、dbに反映させる。

rails db:seed

deviseを使ってログアウト機能を追加する

deviseで作成したユーザー認証機能にログアウト機能を追加します。

app/views/welcome/index.html.erb

<% if user_signed_in? %>
  Logged in as <strong><%= current_user.email %></strong>.
  <%= link_to "Settings", edit_user_registration_path %> |
  <%= link_to "Logout", destroy_user_session_path, method: :delete %>
<% end %>

ログインページに強制移動

app/controllers/welcome_controller.rb

class WelcomeController < ApplicationController
  before_action :authenticate_user!
  def index
  end
end

ログイン時だけ、編集などができる。 - articles_controller.rb

下記の1文を追加することで、ログインしているユーザーしかnew, create, edit, update, destroyができないようにする。

before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]

強制ログインページ飛ばし、フラッシュメッセージ設定の記述 layoutで、強制ログインページ飛ばし、フラッシュメッセージ設定の記述をする。 - app/views/layouts/application.html.erb ````

ユーザがログインしていないなら強制的にログイン画面に飛ばす

  <% if user_signed_in? %>
    Logged in as <strong><%= current_user.email %></strong>.
    <%= link_to "Settings", edit_user_registration_path %> |
    <%= link_to "Logout", destroy_user_session_path, method: :delete %>
  <% else %>
    <%= link_to "Sign up", new_user_registration_path, :class => 'navbar-link' %> |
    <%= link_to "Login", new_user_session_path, :class => 'navbar-link' %>
  <% end %>

フラッシュメーセージの設定

  <p class="notice"><%= notice %></p>
  <p class="alert"><%= alert %></p>
  <%= yield %>
</body>

userモデルにカラムを追加する.(userプロフィールの項目を増やす)

手順1. userモデルにカラムを追加。

rails g migration AddNameToUser name:string
rails db:migrate

手順2. コンソールで確認

コンソールで、カラムが追加できたか確認。

rails console
User.all

カラムが追加されている↓

 name: nil>

手順3. サインアップ画面とユーザ情報変更画面に、カラムを追加する。

viewsを編集して、追加したカラムが表示されるようにする。 なお、registrationsはユーザ情報に関するディレクトリ。

  • app/views/devise/registrations/new.html.erb
<div class="field">
  <%= f.label :name %><br />
  <%= f.text_field :name %>
</div>
  • app/views/devise/registrations/edit.html.erb
<div class="field">
  <%= f.label :name %><br />
  <%= f.text_field :name %>
</div>

これで、カラム追加は完了。ただし、このままでは新規追加したカラムに値を入力してもDBに保存されていない状態。

手順4. Userモデルに新規追加したカラムを、DBに保存できるようにする。

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  # ユーザ認証のアクションを呼び出しているか判別して、configure_permitted_parametersメソッドを呼ぶ
  before_action :configure_permitted_parameters, if: :devise_controller?

# protectedは以下のメソッドを外部からアクセスできないよう指定している。
  protected

# サインアップ時と編集時、不正なコードが含まれていないかをチェックしている。
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
    devise_parameter_sanitizer.permit(:account_update, keys: [:name])
  end
end

[:name]の部分はカラムによって変わる。例えば、imageカラムを追加したなら、[:image]と言うふうにカラム名を記載する。

ログインしているユーザ名で投稿を保存する

image.png

今、新規作成のページでUserを選択できるようになっている。これをログインしているユーザに自動的になるよう編集したい。

手順1. viewsファイルを編集

app/views/articles/_form.html.erbで、Userのラベルの記述部分を消す。

手順2. createメソッドを編集

  • app/controllers/articles_controller.rb
def create
  @article = Article.new(article_params)

def create
  @article = Article.new(article_params)
  @article.user_id = current_user.id

のように追記する。こうすることで、新規作成されたuser_idに、現在のユーザidを代入することができる。

投稿したユーザーだけが自分の記事を編集・削除できるようにする

自分の記事以外も編集、削除ボタンが選択できるようになってしまっている。 自分以外の記事を編集削除したとき、エラーになるようにしたい。

image.png

controllerファイルで、編集削除アクションの実行を、 if @article.user_id == current_user.idの時だけ実行するようにする。 こうすれば、ログインしているユーザーのみ、そのユーザが書いた記事を編集できる。

  • 例. 編集アクション
def update
    if @article.user_id == current_user.id
      respond_to do |format|
        if @article.update(article_params)
          format.html { redirect_to @article, notice: 'Article was successfully updated.' }
          format.json { render :show, status: :ok, location: @article }
        else
          format.html { render :edit }
          format.json { render json: @article.errors, status: :unprocessable_entity }
        end
      end
    else
        redirect_to @article, notice: "You don't have permission."
    end
end

ログインユーザ以外の記事は、編集削除ボタンを非表示にする。

編集削除リンクの箇所を、編集する。

  • app/views/articles/index.html.erb
<% if user_signed_in? && article.user_id == current_user.id %>
    <td><%= link_to 'Edit', edit_article_path(article) %></td>
    <td><%= link_to 'Destroy', article, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>

こうすることで、ログインユーザの記事のみ編集削除ボタンが表示される。

アカウント編集ページで自分のメールアドレスとパスワード、郵便番号、住所と自己紹介文を編集できる(自分以外のユーザーの情報は編集できないこと)

参考: https://qiita.com/gogotakataka1234/items/b094f08583af22e6d26d

手順1. devise_create_users.rbカラム名とデータ型を追記。

  • db/migrate/20~~~~~devise_create_users.rb
def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.integer :post_code
      t.string :address,            null: false, default: ""
      t.text :self_introduction,    null: false, default: ""
以下略
rails db:migrate

手順2. viewファイルを修正。

下記のように、追加したいカラムを追記する。

<div class="field">
    <%= f.label :post_code %><br />
    <%= f.number_field :post_code, autofocus: true, autocomplete: "post_code" %>
  </div>

手順3. 追加したいカラムをストロングパラメータに設定する。

メールアドレスとパスワードは、devise導入の時点でデフォルトでストロングパラメータに設定されている。ストロングパラメータじゃないと、DBに保存されないので、追加したカラムをストロングパラメータに設定する。 - app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_action :authenticate_user!
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:sign_up, keys: [:post_code])
  devise_parameter_sanitizer.permit(:sign_up, keys: [:address])
  devise_parameter_sanitizer.permit(:sign_up, keys: [:self_introduction])
  devise_parameter_sanitizer.permit(:account_update, keys: [:post_code])
  devise_parameter_sanitizer.permit(:account_update, keys: [:address])
  devise_parameter_sanitizer.permit(:account_update, keys: [:self_introduction])
  end
end

ブラウザ上で、郵便番号、住所、自己紹介文を記載できることを確認した。 また、rails cでDBにもちゃんと保存されていることを確認。

validateで、文字数制限をかける。

app/models/user.rbで、バリデーション設定をする。

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  validates :post_code, length: { minimum: 1, maximum: 20 }
  validates :address, length: { minimum: 1, maximum: 50 }
  validates :self_introduction, length: { minimum: 1, maximum: 100 }
end

PostgreSQLの操作まとめ

バージョンを確認

psql --version

postgresql起動

brew services start postgresql

postgresqlの状態を確認

brew services list

サービスのリストを出力することで、postgresqlが起動しているかチェックできる。

% brew services list
Name       Status  User  Plist
mysql      stopped       
postgresql started user /Users/user/Library/LaunchAgents/homebrew.mxcl.postgresql.plist

データベース一覧を表示

 psql -l
% psql -l
                          List of databases
    Name     | Owner | Encoding | Collate | Ctype | Access privileges 
-------------+-------+----------+---------+-------+-------------------
 postgres    | user | UTF8     | C       | C     | 
 template0   | user | UTF8     | C       | C     | =c/user         +
             |       |          |         |       | user=CTc/user
 template1   | user | UTF8     | C       | C     | =c/user         +
             |       |          |         |       | user=CTc/user

データベース作成

まずは、データベースのpostgresにログインする。 データベースを何も作成していない場合、まずはpostgresにログインしてから他のデータベースを作成する。(自分はpostgresqlにログインするのをやっていなくて、数時間ハマりました)

psql postgres
psql (14.5)
Type "help" for help.

postgres=# 

入力待ち状態になる。

↓データベース作成コマンド↓

create database mydb;

テーブル作成

先ほど作成したdbに接続する。

psql mydb

↓テーブル作成コマンド↓

create table books(id integer, name text);
CREATE TABLE テーブル名(カラム名 データタイプ, … );

デーブルの情報は\d テーブル名で確認できます。

mydb=# \d books
               Table "public.books"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           |          | 
 name   | text    |           |          | 

テーブルにデータを追加

全てのカラムにデータを入れる場合(全カラムでnillがない場合)は、順番にカラムの値を指定できる。

insert into books values (1, 'はらぺこあおむし');

指定したカラムにデータを入れる場合、こんな感じで指定する。

insert into books (id, name) values (2, 'ぐりとぐら');

テーブルのデータを取得

  • 全データを取得の場合
select * from books;
mydb=# select * from books;
 id |       name       
----+------------------
  1 | はらぺこあおむし
  2 | ぐりとぐら
(2 rows)
  • 特定のデータを取得の場合
mydb=# select name from books;
       name       
------------------
 はらぺこあおむし
 ぐりとぐら
(2 rows)

postgresqlを停止

brew services stop postgresql

sinatraでwebページを立ち上げる手順

railsを学ぶ前身として、railsほど複雑ではなくrailsより処理が軽い「Sinatra」を学習しました。「Sinatraデータベース連携をしたwebページを立ち上げる手順」をまとめました。

前提

データベース: SQLITE

OS: mac

手順1. sinatra用のディレクトリを作成し、必要ライブラリを入れる。

bundle initで、Gemfileを入れる。

bundle init

入れたGemfileに、以下の項目を追記して、必要ライブラリを入れる。

# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

# gem "rails"
gem "activerecord"
gem "sqlite3", "~> 1.4.4"
gem "sinatra"
gem "webrick"
gem 'sinatra-contrib'

Gemfileに記載したライブラリを、bundle installで入れる。

bundle install

注. rubyのverが最新じゃないと、bundle install失敗するので注意。 (ここでハマった👊)

手順2. データベースのテーブルを作る。

テーブルにデータを入れるための、命令文を書く。 名前は、ここでは命令文の名前をdbinit.sq3、テーブル名bbsdataとする。

dbinit.sq3

create table bbsdata (
  id integer primary key,
  name varchar(30),
  entry varchar(150)
);

insert into bbsdata values (1, 'Diplodocus', 'The first entry.');
insert into bbsdata values (2, 'Allosaurus', 'The second entry.');

その後、書いた命令書通りのデータを、テーブルに送る なお、bbs.dbはデータベースのファイル名である。

sqlite3 bbs.db < dbinit.sq3

データがテーブルに送られているか、確認。 まずは、sqlite操作画面に移動する。

sqlite3 bbs.db

以下のselect文で、bbsdataテーブルの全データを取得する。

sqlite> select * from bbsdata;
1|Diplodocus|The first entry.
2|Allosaurus|The second entry.

手順3. YAMLでデータベースとRUBYプログラムをつなぐ。

現状sqliteのデータベースファイルを作成したが、RUBYと関係のないデータベースファイルが、1つできただけなので、Rubyと結びつける🤝 Rubyファイルとデータベースファイルを関係づけるのがYAMLファイル。

database.ymlを作成し、以下を記入

development:
  adapter: sqlite3 #データベースサーバの種類
  database: bbs.db #データベースのファイル名

その後rubyファイルに以下のような記述をすると、database.ymlが読み込まれて、関連づけることができる。

# データベースを使う設定
ActiveRecord::Base.configurations = YAML.load_file('database.yml')
ActiveRecord::Base.establish_connection :development

上記の記述をどうrubyプログラムに書くかは、例文として後述。👇

これで下準備は完了。 あとは、rubyプログラムと、体裁を整えるerbファイルを作成するだけ🙌

手順4. webブラウザへ表示する。

例として、以下のようなwebページを作る。(表になっていて、空欄部分は入力可能)

image.png

まずは、rubyプログラムを作成する。 下記のように記述。 ※sinatraでwebページを立ち上げるのが目的なので、プログラムの内容については解説しない。

require 'sinatra'
require 'active_record'
require "sinatra/reloader" if development?

set :environment, :production

# データベースを使う設定
ActiveRecord::Base.configurations = YAML.load_file('database.yml')
ActiveRecord::Base.establish_connection :development

# bbsdataテーブルをBBSdataクラスとして、扱えるようにする
class BBSdata < ActiveRecord::Base
    self.table_name = 'bbsdata'
end

get '/' do
  t = BBSdata.all

  @h = ""
  t.each do |a|
    @h = @h + "<tr>"
    @h = @h + "<td>#{a.id}</td>"
    @h = @h + "<td>#{a.name}</td>"
    @h = @h + "<td>#{a.entry}</td>"

    @h = @h + "<form method=\"post\" action=\"/del\">"
    @h = @h + "<td><input type=\"submit\" value=\"/Delete\"></td>"
    @h = @h + "<input type=\"hidden\" name=\"id\" value=\"#{a.id}\">"
    @h = @h + "<input type=\"hidden\" name=\"_method\" value=\"delete\">"
    @h = @h + "</form>"

    @h = @h + "</tr>\n"
  end

  erb :index
end

post '/new' do
  s = BBSdata.new
  s.id = params[:id]
  s.name = params[:name]
  s.entry = params[:entry]
  s.save
  redirect '/'
end

delete '/del' do
  s = BBSdata.find(params[:id])
  s.destroy
  redirect '/'
end

viewsディレクトリを作成する。 こちらにはレイアウトを決めるlayout.erbと、ページ本体であるindex.erbを入れる。 最悪layout.erbは無くても表示はできる。 (layoutはテンプレートのような意味合いで、たくさんのerbファイルを修正するときに、 layout.erbが有用らしい👆)

  • index.erb
<table border>

<tr>
<th>ID</th>
<th>Name</th>
<th>Entry</th>
</tr>

<%= @h %>

<form method="post" action="/new">
<tr>
<td><input type="text" name="id"></td>
<td><input type="text" name="name"></td>
<td><input type="text" name="entry"></td>
<td><input type="submit" value="Go"></td>
</tr>
</form>

</table>

以下コマンドでwebページに出力する。

bundle exec ruby dbtest.rb -o 0.0.0.0
  • 実行結果

image.png

👏完了👏

「不要なコミット削除方法」+「githubのリモートの内容をローカルに持ってくる方法」

記事内容

  1. 不要なコミット削除方法
  2. git resetをして、ローカル内容が消し飛んだ時に、リモートの内容を引っ張ってくる方法

上記2点でハマったので、忘備録を兼ねて記事にしました。

1. 不要なコミットの削除のやり方

pull requestに、関係のないファイル(他のPRでコミットされたファイル)がコミットされてしまった。 原因はブランチを切るところを間違えたことと推測される。 その時の対処法をまとめた。

1. brew install tigでtigをインストール

用途としてはgit logと同じだが、tigの方が見やすいので、インストールした。 (こっちの方が、git logより見やすい。)

該当のブランチに移動して、 tig を打ち込んで、コミット履歴を確認する。

image.png

全てのコミットが表示されるので、消したいコミットがあることを確認。

2. git rebase -i HEAD~4で、いらないコミットを消す

最新から4番目以内の編集ができる。 (例えば4ではなく、6にすると、6番目までを編集可能) tigでいらないコミットが上から何番目にあるかを確認して、何番目まで編集可能か決めるといい。

image.png pickをdropに書き換えると、消すことができる。 (行自体を消す、でも可能だが、dropに書き換える手法の方が、後々わかりやすい。)

3. git push origin calendar --force-with-leaseで、ローカルの内容をリモートに反映

git push origin calendar でpushしようとしたが、conflictエラーが発生(リモートとローカルに差分があるので、できない状態)。 →オプションに、--forceを付けることで、差分があっても、無理やりローカルの内容をリモートに反映させられる。(リモートの内容は全て無視して壊す)

with-leaseオプションは、他人がリモート上で編集を行なっていた場合に、自分がpushをする時に警告が出てくれるオプション。(警告が出たら、他人がリモートで作業しているということなので、他人に確認を取ってから、pushしてね、ということ)基本はwith-leaseをつけた方が無難。

2. git resetコマンドを実行してしまい、ブランチが消えてしまった時の対処法。

1. git fetch origin.を使って、リモート上のブランチ全てのファイルを取ってくる。(※2番のやり方の方が無難)

→持ってこれるのは、あくまで自分が最後に編集した状態の、リモートの状態(他人がリモートで編集していた場合は、その差分は含まれない) →含みたい場合はpull ローカルとの差分があっても、その差分は持ってこない。 差分ある場合は、ターミナルの設定によっては、最新かどうかの警告が出る。 全部の内容を持ってくるので、情報が多くなってしまう。

2.git branch ブランチ名 origin/ブランチ名でファイルを指定して、リモートから内容を持ってくる

git branch ブランチ名 origin/ブランチ名

上記コマンドで、リモート上のファイルを指定して、リモートの内容を引っ張ってくる。

[追記] 他の関係のないコミットが混ざってしまう原因。

原因

ローカルのmainがリモートの状態より進んでいたから、pushした時に不要なコミットが混入していた。 →自分としてはgit pullをしたので、ローカルとリモートのmainの状態が同じだと勝手に思い込んでいた。 →ローカルの方が進んでいると、git pullをしてもリモートとローカルの状態は同じにならない。

git pullについて

git pullはローカルの方がリモートよりも進んでいない場合に、リモートと同じ状態にすること。 今回の場合はローカルの方がリモートより進んでいたので、pullしたとしても、もともとローカルで進んでいたコミットが消えたわけではない。そのため、pushした時にプルリクに含まれた。

やったこと

ローカルのmainを消去して、remoteのmainをpullする。(ローカルとリモートを同じ状態にする。→不要なコミットが混ざらない。)

git branch -D mainで、ローカル上のmainを消す。 (-Dは強制消去。-dは安全に消去) →git branch上で、mainが消えていることを確認。 ② git pullする。git branch上で、mainがpullされたことを確認。 これで、リモートのmainの状態がローカルに反映された。

ちなみに、 git diff main origin/main で、main(ローカル)とorigin/main(リモート)の違いを確認できる。 (もし違いがなければ、コマンドを打っても何も表示されない。)

ペアプロで学んだコマンド集

① ctrl + r

過去に入力したコマンドを参照できる。 ctrl + r と打つと、下記画像のような状態になる。 image.png

例えば、git diff main origin/wc-new を参照したいなら、画像の状態でgit diと途中まで打てば、過去に打ち込んだコマンドに当てはまるものが候補として表示される。

image.png

② git cherry-pick コミット番号

git cherry-pick c4cb46c5a4e6b97126bb3a723cbf6b38582d0796

現在いるブランチに、他のブランチのコミットを持ってくる。 コミット番号は5桁表示すればOK.(全部打ち込む必要ない)

③ git log --pretty=format:"%C(green)%h %C(blue)%ad %C(red)|%C(reset) %s%d [%an]" --graph --date=short -4

git log --pretty=format:"%C(green)%h %C(blue)%ad %C(red)|%C(reset) %s%d [%an]" --graph --date=short -4

git logをより詳細に見ることができる。 これは、u1tnkさんのエイリアス

image.png

④ git push -f origin wc-new

git push -f origin wc-new

強制push

⑤ git branch -a

git branch -a

image.png ローカルの中にもremoteの状態内容があって、それを表示する。 git pullをすると、この中にある、remotes/origin/mainが参照される。