プログラミング学習

Rubyやrailsについて学んだことをアウトプットしています。

【Paiza】Bランクレベルアップメニュー

今回はpaizaのBランクレベルアップメニューの「五目並べ(横) (paizaランク C 相当)」を解いていきます。

問題文

5行5列の五目並べの盤面が与えられます。

盤面の各マスには、"O"か"X"か"."が書かれています。

"O"と"X"は、それぞれプレイヤーの記号を表します。

同じ記号が横に連続で5つ並んでいれば、その記号のプレイヤーが勝者となります。

勝者の記号を1行で表示してください。 勝者がいない場合は、引き分けとして、"D"を表示してください。

入力例1 XXOXO OXOXX OOOOO OXOX. XOXXO

出力例1 O

回答方法

最初にこの問題で出力しなければならない要素からコードを考えていきます。

・結果を変数に代入する。

result = "D" # デフォルトでは引き分けに設定し、結果に応じてこの中身が変化するようにする。

・プレイヤーの記号を配列に代入する。

array = [X, O] 

・プレイヤーごとに5つ連続で横に目がそろうかを確認する。

(1..5).each do # 5回入力が行われるのでそれぞれの行で以下の検証を行う。
  string = gets.chomp.split('')
# 5行に渡って入力される値を空白で分けて配列として受け取っている。
  array.each do |a|
    cnt = 0
    # arrayのeachメソッド内でcunは定義されているのでOとXでそれぞれcntの中身は変わる
    string.each { |s| cnt = cnt + 1 if s == a }
    # 二重で繰り返し処理が行われている。string配列を1行ずつ取り出す。
    # さらに一文字ずつ取り出してarrayのaと一致するかを確認。一致した場合はカウントを1増やす。
    result = a if cnt >= 5
  end
end

・結果を出力する。

puts result 

これで指定された出力を行うことができました。

【Rails】メイラー機能について

今回はRailsでのメイラー機能について学んでいきます。

・メイラー機能の実装
・ユーザー全員に該当メールを送信したい場合
・メイラー機能の確認


メイラー機能の実装

メイラーはコントローラーととても役割が似ています。
コントローラーと同じく、以下のジェネレーターで作成することができます。
rails generate mialer TasksMailer


次にapp/mailers/questions_mailer.rbにおいてメールを送るためのメソッドを作成する。

class QuestionMailer < ApplicationMailer
#クラス定義でApplicationMailerをスーパークラスに指定しています。 
    def creation_email(question) # 引数でQuestionオブジェクトを受け取っている。
        @question = question
メール本文で扱うためインスタンス変数に代入している。
        mail # メールを作成・送信するためのメソッド(
            subject:"質問投稿通知メール",
   #タイトルを指定
            from: "tsunemi0217@icloud.com",
   #送信元を指定
            to:"tsunemi0217@icloud.com"  
   #宛先を指定
        )
    end
end

コントローラーの設定が完了したらメールのテンプレートを作成していきます。

今回はHTMLとテキストどちらの形式も作成するスタイルを取ります。
その理由としては例えば携帯電話向けにはテキストメールを送り、PC向けにはHTMLメールを送りたい、という要望が存在するからです。
このような方式をmultipart alternative方式というので覚えておきましょう。

app/views/task_mailer/creation_email.html.erb

# html形式
<p>以下の質問が投稿されました。</p>
<ul>
    <li>
    <%= @question.title%> # コントローラーから受け取ったインスタンス変数から表示したい要素を呼び出している。
    </li>
    <li>
    <%= @question.body%>
    </li>
</ul>

# text形式
<p>以下の質問が投稿されました</p>
<br>
<%= @question.title%>
<br>
<%= @question.body%>


以上でメイラーの設定は完了です。次にメイラーを呼び出すためのコードをコントローラーに設定していきましょう。

今回はタスク設定後に通知メールを設定したいのでquestionsコントローラーのcreateアクションを以下のように変更します。

  def create
    @question = Question.new(question_params)
    @question.user_id = current_user.id
    @question.save!

    QuestionMailer.creation_email(@question).deliver_now
 # QuestionMailerクラスのcreation_emailメソッドを呼び出している。引数には今回の質問内容が代入されている@question変数を受け取る。
   #deliver_nowは即時送信を行うメソッドである。
    redirect_to questions_url
  end

以上で質問が投稿された際にユーザーに通知メールを送信する機能が完成しました。


ユーザー全員に該当メールを送信したい場合
class AdminMailer < ApplicationMailer
  default to: -> { Admin.pluck(:email) },
# ユーザーを管理しているAdminクラスにpluckメソッドを使用することですべてのユーザーのメアドを配列で受け取っている。pluckメソッドは引数のカラムのデータを配列で受け取る役割を持っている。
          from: 'notification@example.com'

  def new_registration(user)
    @user = user
    mail(subject: "New User Signup: #{@user.email}")
  end
end



メイラー機能の確認

最後に実装したメイラー機能が機能するかを確認します。
確認のためにはmailcatcherのgemを使用します。

gem install mailcatcherでgemをインストールします。
config/enviroments/development.rbでmailcatcherを使用できるように設定を変更します。

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false
# メールの送信に失敗した場合エラーを出すかどうかを設定することができる。
  config.action_mailer.delivery_method = :smtp
# メールの送信方法を指定してくれている。smtpもメール送信方法の1つを表している。
  config.action_mailer.smtp_settings = {address: '127.0.0.1', port: 1025}
# smtpの詳細設定を行っている。ここではportとaddressでSMPTサーバーのポート番号とSMTPサーバーのホスト名を設定している。
  ```
mailcatherを起動して送信されるか確かてあげましょう。<br>
<br>

無事に送信されていればメイラー機能は問題なく実装されています。


<br>
<br>



参考資料:
[https://qiita.com/annaaida/items/81d8a3f1b7ae3b52dc2b]

10月の学習を振り返って

今回は10月からの学習を振り返って良かった点と反省点をまとめて11月の目標を考えていきたいと思います!!

・合計勉強時間と内訳

・良かった点

・反省点

・11月はどう勉強していくか

合計勉強時間と内訳

勉強時間に関してはStudyplusを活用して記録しています。

10月の合計勉強時間は  約130時間でした。

内訳としては
・webの仕組みについて  4.5時間
アプリ開発      21.5時間
・gitについて       6時間
Rubyについて      24時間
railsについて      41時間
・Paiza          20時間
・勉強内容のまとめ    8時間

この記録をもとによかった点と反省点をそれぞれ振り返っていきます。

良かった点

・ほぼ毎日継続して何かしらの勉強をすることができた。
31日間の内勉強時間は置いといて30日間はプログラミングの勉強ができたので勉強の習慣化ができたと思います。

これに関してはgithubのTILを毎日更新して草を絶やさないようにしようとしたのが効果的だったと感じています。
Studyplusなどの勉強時間管理アプリもそうですが、僕は何かしら形に残って自分の頑張りが見れることがモチベーションに繋がることがわかりました。


・webの仕組みやRubyについて学ぶことでRailsの理解が深まった。

10月以前は基礎的な内容を学習せずにRailsを使用していました。
その結果としてRailsに書いている内容が全く理解できず、ネットで探したコードをただコピペしているという状況でした。

しかし、10月からhttpなどのweb基礎やRubyの文法などについて勉強を行ったのでRailsで自分が書いているコードの意味が理解できるようになりました。

プログラミングで大切なのはコードを書くことではなくコードを理解することであると実感しました。

・エラーについてブログでまとめるようになった。
今までエラーが出たときはネットで調べてヒットしたものを試していくという方法で解決していました。
しかし、これではエラーの原因・解決方法への理解が甘くなってしまい同じようなエラーに遭遇しても解決することができないことがよくありました。

そこで10月の後半からこのブログ上でエラーの原因についてまとめることにしました。
誰かに見られるかもしれないと思うとより詳しく原因と解決策について調べるようになり、理解が深まりました。

反省点

・週に1度の頻度でモチベーションが低下してしまった。
毎日少しでも勉強を行うというハードルはクリアすることができたのですが、勉強時間に関しては1日1時間の日があったりなど大きくぶれがあります。
特に週に1度の頻度でモチベーションの低い日が来てしまいます。

今後の対策としては習慣として毎日行うことの数を増やしていくことが挙げられます。

最初は毎日githubのTILを更新することだけが習慣だったのですが、最近ではブログで記事を書くことも毎日の習慣になっているのでこの調子で1日の最低限タスクを増やすことでブレの少ない勉強時間が確保できると考えています。

・「理解した」の基準が甘く同じ機能に時間を取られてしまった。
これに関しては前回の記事でも書きましたが、書籍のコードを写して書いただけで「理解した」と考えてしまっていました。
理解が甘いと同じ機能を実装する際にまた、書籍で調べてという風に時間の無駄が生まれてしまいます。
なので、今は「理解した」=「該当コードをすべて説明できること」と定義して学習を行うようにしています。

・学習に関して計画性がない。
いつまでにアプリを開発するや書籍を読むなど目標を明確化しないままに学習を行ってしまっていました。
なので、勉強の進捗が遅くなってしまっていたと感じます。対策としては毎日記録するTILに今月、今週、今日の目標を明記することが挙げられます。
そして、達成できなかった場合はなぜ達成できなかったのか理由を書くようにしていきたいと考えています。

11月はどう勉強していくか

10月の学習まとめを考慮して11月からは以下のように学習を行っていきたいと思います。

① 毎日行う最低限のタスクを増やす。
現状のTIL、ブログに加えてPaiza問題1日5問
② 曖昧な理解をしないようにする。
自分が学んだ内容に関して全て説明できるようにする。
③ TILに目標を明記する。
目標が達成できたかどうかで勉強方法を細かくトライアンドエラーする。

これらを意識して11月も勉強頑張ります!

【Rails】Resourcesは何をしてくれているのか

今回はrailsでよく使うメソッドのresourcesについて学んでいきます。

というのも、オリジナル開発アプリを作る中でresources以外のアクションを追加しようとした時に方法がわからず詰まってしまいました。
これはresourcesの中で何が起こっているのか認識できていないことが問題だと感じたのでしっかり理解していきたいと思います。

・resourcesメソッドとは

・resourcesはどのようなルーティングを生み出してくれているのか

・onlyとexceptを使いこなして可読性を高めよう

・ 7つ以外のルーティング設定について

resourcesメソッドとは

resourcesメソッドとは、railsで定義されている7つのアクションのルーティングを自動で作成するメソッドです。 【Rails】 | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

7つのアクションとは
index, show, new, create, edit, update, destroy
のことを指します。

これらを1つ1つ設定することなく、自動でルーティングしてくれるのでとても便利なメソッドですね!

resourcesはどのようなルーティングを生み出してくれているのか

7つのアクションを自動でルーティングしてくれる便利なメソッドですが中でどのような設定を行ってくれているのか理解しないと今回の僕のように苦労してしまいます。

一度確認してみましょう。

   get 'tweets'     => 'tweets#index'
    get 'tweets/:id' => 'tweets#show'
    get 'tweets/new' => 'tweets#new'
    post 'tweets' => 'tweets#create'
    get 'tweets/:id/edit' => 'tweets#edit'
    patch 'tweets/:id'  => 'tweets#update'
    delete 'tweets/:id' => 'tweets#destroy'

show, edit, update, destroyアクションにはそれぞれidが指定されていますね。

これらのアクションは特定のオブジェクトに対してアクションを行うのでidが必要になります。

onlyとexceptを使いこなして可読性を高めよう

onlyとexceptを使用すると特定のアクションだけを指定することができます。

指定することによってコードを読んだときにアクションを明示できるので可読性が高まります。
また、rails routesコマンドを使用するときなどに表示される項目を減らすことができます。

コードの書き方は以下になります。

resources :tweets, only: [:index, :snow]
# 指定されたアクションのみをルーティングします。

resources :tweets, except: [:new, :create, :edit, :update, :destroy]
# 指定されたアクション以外をルーティングします。
7つ以外のルーティング設定について

resourcesでは先ほど紹介した7つのアクションしかルーティングを設定することができません。
よって、他にもルーティングを追加したいときはmenberかcollectionを使用する必要があります。

menberは以下のようにコードを書きます。 menberの特徴は「idで指定した個々のリソースに対してアクションを設定することができる」ことです。

  resources :tweets do
    member do
      get 'review'
    end
  end

collectionは以下のようにコードを書きます。 collectionの特徴は「リソース全体に対するアクションを定義することができること」です。

resources :tweets do
    collection do
      get 'search'
    end
  end

それぞれ用途によって使い分けていきましょう。

参考記事:

【Rails】 | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

【情報収集】Qiitaで勉強になった記事

プログラミングを勉強していく中で最新情報や学習方法など様々な情報を得ることが大切だと考えています。

なので、今回はQiitaというエンジニア特化型の情報発信サイトから自分が為になったと感じた記事をいくつか紹介させてもらいます。 皆さんも気になる記事があればぜひ読んでみてください。

今回紹介する記事

プログラミング勉強を加速させる7つの習慣 - Qiita

プログラミング勉強を加速させる7つの習慣

この記事では社会人になって初めてプログラミングを勉強した著者の体験から最適な勉強を行うための習慣を教えてくれます。

習慣に関しては勉強分野を絞ることから筋トレまで多岐にわたるのですが、私が特に為になったと感じたのは 習慣2.まず「理解した」を定義する の部分です。

ここでは「理解した」の定義を曖昧にしてしまうと自分が想定している基準の実力が身につかないことがあるという内容が述べられています。

この話に私はとても共感しました。 私自身CRUD機能に関して本を読みながら実際にコードを書いてみたことを「理解した」ことに無意識で定義していましたが、次に同じ機能を実装しようとした時に方法がわからず前回と同じように本を読みながらコードを書くということを何度も行ってしまっていました。 この状態はまさに「理解した」の定義を曖昧に設定したことによって自分に必要な力が身についていない状態でした。

この記事から自分の学習方法に危機感を覚えたので、ちゃんと自分が習得したい力のレベルとそれに沿った「理解した」の定義を行いたいと思います。

習得したい力:私は自分の書いたコードについて他の人に説明できるようになる力を身に着けたいと思います。

「理解した」の定義:他の人に説明するためにはコードについて質問されたときに全て回答できることが必要になると思うので、それぞれのコードについて説明ができることと定義します。

今後の勉強はこの定義のもとで行うので自分の中での齟齬がなくなりそうです。 皆さんもぜひ試してみてください!

【Rails】Ransackで検索機能を実装しよう

今回はオリジナルアプリ開発を進める中で検索機能の実装を行ったのでその方法について説明していきます。

・gemをインストールしよう

・コントローラーの設定

・ビューの設定

gemをインストールしよう

検索機能を実装するために今回はRansackというgemを使用します。
このgemを使用することでとても簡単に検索機能を実装できるのでぜひ活用していきましょう。

ということで、gemfilegem 'ransack'を追加してbundleコマンドでインストールを行いましょう。

コントローラーの設定

gemのインストールが完了したら次はコントローラーの設定を行いましょう。
今回は架空の質問投稿アプリがあるものとしてコードを書いていきます。

app/controller/questions_controller.rb

def index
  @q = current_user.ransack(params[:q])
  @questions = @q.result(distinct: true).recent
end

ここで使用されているメソッドについて説明します。

・.ransackメソッド…送られてきたデータをもとにデータベースからデータを検索してくれるものです。
・params[:q]…ビューファイルから送られてくるデータが格納されています。
・.result…取得したデータをActiveRecord_Relationのオブジェクトに変換してくれます。


これでコントローラー上での設定は完了しました。
最後にビューファイルに変更を加えましょう。


ビューの設定

ビューでは検索フォームの作成を行います。
コードは以下のように書きます。

<%= search_form_for @q do |f| %>
  <%= f.search_field :name_cont %>
  <%= f.submit %>
<% end %>


ここでもそれぞれの要素について説明します。


・search_form_for…検索フォームを作るためのHTMLを出力してくれます。
form_withなどの検索版であるとイメージしてください。

・name_cont…カラムのどの要素で検索を書けるのかを決めてくれています。
今回だとnameなのでユーザーの名前で検索をかけてくれます。この部分を指定したいカラムに変更することでそのカラムについての検索ができます。

以上で検索機能の実装についての説明を終わります。
ここでは紹介できなかった要素もたくさんあるので興味のある人はより深く調べてみてください。

参考資料:


【Rails】 ransackを使って検索機能がついたアプリを作ろう! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

【Rails エラー】指定したアクション以外に繋がってしまうルーティングエラーの原因と対処法

今回もオリジナル開発で遭遇したルーティングのエラーについて原因と対処法を見ていきます。

今回発生したのは以下のエラーです。
f:id:yusuke_learning:20211029174606p:plain これは質問投稿アプリにおいてユーザーを管理する管理者画面から質問一覧を表示するためにadmin/usersのビューファイルにquestion.html.erbを追加し、ルーティングを設定した際に発生しました。

まずは、エラーコードから原因を推測していきます。

・エラーコードから原因を読み解く


エラーコードでは

RecordNotFound in Admin::UsersController#show

と書かれているのでコントローラーのshowアクションで問題が発生していることがわかります。
さらに詳しく見ていくと

Couldn't find User with "id" = question

つまり、showアクションではオブジェクトごとのidを受け取って詳細を表示しているのですがそのidにquestionが代入されており、そんなidは見つからないと言っています。

エラーコードから読み取れた内容をまとめると

①ルーティングで指定したadmin/users#questionではなくadmin/users#showが起動している。

②idになぜかquestionが代入されている。

この2つの謎を解明できればエラーが解決できそうです。
そこでルーティングについての記述のあるroutes.rbファイルを確認してみます。

・原因を特定する


該当箇所を見るとresourcesでCRUD機能に必要なルーティングを設定し、今回新たに追加した
get"/users/question", to:"users#question"
がその下に書かれています。

f:id:yusuke_learning:20211029180643p:plain
routes.rb
コードを見ただけではなぜ"/users/question"から"users#show"が起動されるのか理解できませんでした。
ここでしばらく悩んでしまったのですが、同じようなエラーで苦しんでいる人がいないかと検索したところ以下の記事が見つかりました。

Ruby on Rails - 【Ruby on Rails】違うアクションが実行されてしまう|teratail

記事の投稿者さんも自分と同じエラーに苦しんでいました。 そして、回答を見てみると

resourcesで定義したルートの場合、hogehoge/indexはhogehoge/:idの方にヒットして、「id=indexでshowを呼び出す」という意味になります。

つまり、エラーの原因はresources :usersの下に
get"users/question", to:"users#questionを定義してしまったことによって
"users/question"がhogehoge/:idと認識されてしまったことでした。
これでなぜshowアクションに遷移したのか、そしてidになぜquestionが代入されていたのかが判明しました。

・解決策


解決策としてはresources :usersよりも上の行に追加したいルーティングを書くことです。
これによって、想定したアクションに遷移させることができました。

resourcesにこのような特徴があるとは知らなかったので今後は気を付けていきたいと思います。

以上で今回の記事を終わります!

参考記事:


Ruby on Rails - 【Ruby on Rails】違うアクションが実行されてしまう|teratail