20201104のRubyに関する記事は30件です。

webサイトが画面が表示されるまでの仕組み

ウェブサイトの画面が映る仕組み

分かっていそうで理解しきれていなかった内容をまとめていきたいと思います。

重要ワード

  • IPアドレス
  • ドメイン
  • DNSサーバー
  • スキーム
  • パス
  • クライアント

基本の理解

https://qiita.com/questions/new
例えば今アクセスしているURLはこんな感じになっています!

この中で"https" この部分のことをスキームといいます。
簡単にいうとどんな手段で通信するの?
といった意味です。今では大体はhttpsではないのでしょうか?

ちなみにスマホとかでよく"このサイトは安全ではありません"とか出てくることがあるのは
httpsではなくhttpが使われている場合です!

httpsとはデータが送信される時にそのデータが暗号化されるようになっています。
これに大してhttpは通信が暗号化されていないと言ったセキュリティに関して少し甘いところがあります!

もしデータが抜き取られてしまった時に暗号化されていた方が安心ですよね。

つづいて"qiita.com"の部分はドメインと呼ばれています!
ドメインとは簡単にいうとインターネット上の住所なようなものです!

これは必ず他のドメインとは被ってはいけないというルールがあります。

つづいて"question/new"これはパスですね。
ドメインの中のどこにアクセスするかを表しています!!

これでURLが何を表しているかざっと理解できたかと思います!

本題

ではここからどうやってwebが画面上に映し出されるか説明していきたいと思います。

①まずはクライアントでURLにアクセスします!
(クライアントというのは端末のことです。主にスマホやPCのことを指します)

②クライアントはこれをDNSサーバーに対して、このドメインのIPアドレスを教えてとお願います!!
おっとここで色々なワードが出てきましたね笑

一つずつ説明していきます。
IPアドレスというのはネットワークにアクセスするために振り分けされる番号のようなものです。
このIPアドレスでもURLでもどちらでもネットにアクセスすることが可能になっています!

DNSサーバーというのはドメインに対してIPアドレスを調べることができるサーバーのことです!

つまりクライアントがqiita.com(ドメイン)のIPアドレスを教えて〜とDNSサーバーに投げると
DNSサーバーは"×××.+++.+++.---"だよ〜みたいな感じでIPアドレスをクライアント側に返します。

③クライアントはそのIPアドレスのwebサーバーに接続します!
さらにパス部分のquestion/newのページを開くようサーバーに要求します!

④これによりwebサーバーがクライアントに対してHTMLを発行し、URLの画面が映し出されます!

だいぶ駆け足になってしまいましたが以上がwebサービスが画面に映し出されるまでの仕組みです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

deviseで記述があっているのに、ログアウトできない現象

はじめに

 deviseを導入してユーザー管理機能を実装していたが、予期せぬエラーに見舞わせたので、記録しておく。

エラー内容

Routing Error
No route matches [GET] "/users/sign_out"

<%= link_to 'ログアウト', destroy_user_session_path, method: :delete, class: :logout %>

もちろん、method: :deleteとビューファイルにも記述していた。なぜか、ルーティングでHTTPメソッドがGETのものを探し出していた。

ローカルサーバーを再起動させる

ターミナルで
「control + c」
入力。
再び、ターミナルで「rails s」実行

荒技!?

config/initializers/devise.rb/269行目
config.sign_out_via = :delete

:delete:getに変える。

最後に

 記述もあっているのに、なぜこのエラーが出たのか、いまだにわからない…。全く同じ記述でも、エラーが出る時と出ない時がある。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby縦書き

rubyで縦書きする方法

結論

a = gets.chars
puts a

例えば下記のようにgetsにtokyoを当てはめると

a = Tokyo.chars
puts a

出力結果

T
o
k
y
o

という感じになります

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ActiveStorageを用いた画像表示で陥ってしまったミス

本記事は正しく機能を実装できている方には無縁かもしれません・・・
ActiveStorageを用いたメッセージ投稿機能のようなものを作成していました。投稿したメッセージを表示するビューファイルを作成したので挙動を確認しようとしたところエラーが発生しました。ロジックは合っているのになぜ・・・

原因

開発途中で挙動確認をしていた際、画像を添付していなくても投稿できたことがあったことを思い出しました。
has_one_attachedによるアソシエーションがうまく組めていなかった時にメッセージだけの投稿データがテーブルに登録されていました。前述の通りアソシエーションを組んでいたため今回作成したビューファイルを開く際にエラーが発生しました。

解決方法

私の場合はテーブルの状態を確認できるSequelProを導入していたので、当該レコードのみを直接削除して対応しました。本来であればテーブルに対してresetを行う方が正しいとは思いますが、個人の開発であればこちらでも良いのかな、、、(良くない)

以上、ロジックだけではなく違う側面も考えられる広い視点が必要だと感じた出来事でした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

正規表現についてメモ

正規表現

正規表現とは、文字列の一部分を抽出・置換したり、文字列が制約を満たしているかを調べるための表現方法。

正規表現を用いるシーン
登録フォームに電話番号を記入する欄の場合。ハイフンを付けて入力する人もいれば、ハイフン無しで入力をする人もいる。フォーマットを統一させるために、入力された電話番号にハイフンが入っていたら必要に応じて処理を行う。

入力欄:090-1234-5678

           ⇓   ハイフンを取り除く

    09012345678

このように、文字列に特定の文字が含まれているかを確認、特定の文字を取り除くなどの操作を行うための技術を正規表現という。


正規表現を利用するための2つのメソッド

◾subメソッド
◾matchメソッド

◾sub <置換>
subメソッドは、文字列の指定した部分を別の文字列に置き換えるためのメソッド。
第1引数に置き換えたい文字列を指定し、第2引数に変換後の文字列を指定。また、操作したい文字列は/で囲む。

(例) 「パンを食べる」という文字列が「ご飯を食べる」という文字列に置換。

irb(main):001:0> str = "パンを食べる"
=> "パンを食べる"

irb(main):002:0> str.sub(/パン/,"ご飯")
=> "ご飯を食べる"


◾match <抽出・制約調査>
matchメソッドは、引数に指定した文字列がメソッドを使用した文字列に含まれているか否かをチェックするためのメソッド。含まれている場合は、指定した文字列がMatchDataというオブジェクトが戻り値で得られる。含まれていない場合は、戻り値としてnilが得られる。

(例) 「Good morning」という文字列に、「Good」という文字列が含まれているか否かチェックする

irb(main):001:0> str = "Good morning"
=> "Good morning"

irb(main):002:0> str.match(/Good/)
=> #<MatchData "Good">

irb(main):003:0> str.match(/Hello/)
=> nil


MatchData
マッチした文字列はMatchDataという種類のオブジェクトで返される。MatchDataから実際にマッチした文字列などを取り出したい場合は、配列から最初のデータを取り出す時と同様の形で取り出すことができる。

irb(main):001:0> str = "good morning"
=> "good morning"

irb(main):002:0> md = str.match(/good/)
=> #<MatchData "good">

irb(main):003:0> md[0]
=> "good"


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby Goldに合格したので、勉強方法をまとめてみた(2020年10月版)

Ruby Silverに合格したので、勉強方法をまとめてみた(2019年2月版)
の続編。

先日Ruby Goldに合格した。90点だった。中々頑張ったと思う。
需要のほどは分からないが、忘れないうちに勉強方法をまとめてみる。

単に勉強方法を並べるだけでは面白みに欠けるので、
各学習段階における本番のスコア予想を完全な独断と偏見に基づいて示してみる。
つまり「ここまでやれば本番でこの位の点数になる気がする(無責任)」という話。

勉強の結果どのくらい合格に近づいているか?というのは、モチベ維持にも役立ちそうだと思い添えてみた。
まぁ私の感覚に基づくものなので、記事の賑やかしとして参考程度に捉えてほしい。
(メインコンテンツはあくまで勉強方法!)

とりあえず結論

  • さらっと試験範囲に目を通す(予想スコア: なし)
  • Rubyのオブジェクト指向をがっつり学ぶ(予想スコア: 50-60点)
  • 問題集を繰り返し解く(予想スコア: 70-80点)
  • 先人の残したブログで知識を補う(予想スコア: 85点以上)

前提

学習開始時点での私のRuby経歴

  • 実務で半年〜1年。(Ruby以外の言語を含めると実務トータル2年弱程度)

学習期間 & 学習時間

  • 学習期間: 2週間ちょっと
  • 学習時間: 40〜50時間(平日2,3時間、休日5時間)

本題: 勉強方法

さらっと試験範囲に目を通す(予想スコア: なし)

まずは大まかに試験範囲のイメージを掴む。
ググって出てきた合格記事を上からいくつか読み比べて、試験範囲の大まかな特徴がつかめればOK。

以下の書籍の 2〜5章でRuby Goldの試験範囲を眺めるのも良い。
[改訂2版]Ruby技術者認定試験合格教本(Silver/Gold対応)Ruby公式資格教科書

すると恐らく以下のような傾向が見えてくると思う。

  • オブジェクト指向に関する設問が全体の半分強を占める
    • 特異クラス?メソッドの継承ツリー? あとメタプログラミングRubyを読むと良いらしい?
  • 残りの半分弱は、実行環境・文法・ライブラリ等から少しずつ出題される。
    • 「これいつ使うんだろう?」って話もたくさん。。。^^;

ひとことで言えば、
「オブジェクト指向関連はガッツリ学ぶ必要があるようだが、その他は種類が多くてよくわからん」
という印象を持つだろう。

その認識は正しい。Ruby Goldの実態は大体そんな感じだ。

本記事の構成の話

ということで本記事では以降、

  • 「オブジェクト指向関連」をどうガッツリ学べば良いか?
  • 「その他は種類が多くてよくわからん」箇所をどう押さえていけば良いか?

の2点を中心に説明していく。

学習完了時点での予想スコア

なし

この時点では特に学習の成果を気にする必要はないだろう。ウォーミングアップみたいなものなので。

「オブジェクト指向関連」をガッツリ学ぶ(予想スコア: 50-60点)

前述の通り、試験問題の半数強はオブジェクト指向関連の設問になる。
まずはここを押さえるのが手堅いだろう。

Ruby Goldにおけるオブジェクト指向関連の設問は、例えば以下のような内容を含んでいる。
(本記事では便宜上これらを「Rubyのオブジェクトモデル(に関する知識)」と呼ぶ事にする)

クラスの継承・Mix-inを考慮したメソッドや定数の探索順, 特異クラス・特異メソッド・クラスメソッド, インスタンス変数(クラスインスタンス変数)・クラス変数・定数等のスコープ, etc...

読むべき本(テンプレ)の話

ではRubyのオブジェクトモデルをどのように"ガッツリ"学べば良いか?
幸いな事にこれにはもうテンプレがある。以下の書籍を読めば良い。

この2冊はRuby Goldを受けるなら可能な限り手に入れた方が良い。
(他の教材はおおよそネットで無料で手に入る)

ここがRuby Goldの山場だという話

この辺りの知識(特にメタプログラミングRuby)は一度で理解するのが難しいかもしれない。ただ、ここだけは真正面から取り組んだ方が良いし、Ruby Goldに関係なくその価値がある。繰り返し読み、関連知識をググり、できる限り手を動かす事をオススメする。内容としては教本の方が少しやさしいのでそちらから手を出すのも良いだろう。(大したアドバイスができず申し訳ない...他にも良い記事いっぱいあるのでググって...)

何度読んでも分からない場合はまだRuby Goldは少し早いのかもしれない。もう少し経験を積んで改めて挑戦することを考えてもいい。(私も以前メタプログラミングRubyを読もうとして途中で挫折した経験があったり)

逆に言えばこれ以上難しい話はRuby Goldの試験範囲には存在しない。これ以降は(めんどくさいことはあっても)全く理解できない内容は出てこないだろう。ここが山場なので気合いを入れて学習したい。

メタプログラミングRuby(1〜5章)の内容が8割程度理解でき、オブジェクト・クラス・特異クラスの関係性の図(5章の図5-5)を頭の中で思い描けるようになる辺りが学習完了の目安だろう。もしくは以下のサイトの図も理解度を測るちょうど良い目安になると思う。

「クラスはオブジェクトである」に辿り着くまで

ちょっと足りない話

実はこの2冊だけだとオブジェクトモデル関連で少し弱い点がある。軽く学習方法を紹介する。

定数探索周り

定数探索は「最初はレキシカルスコープ、見つからなかったら継承チェーン」
ということだけ覚えて少しググってほしい。
(絶対参照/相対参照辺りは一旦理解を保留しても良い。あくまで調査した範囲だが、Ruby Goldではその点をあまり問われない。全く無いとは言えないが...)

きっちりした情報がほしいという人はRubyの仕組み の第6章が参考になる。
該当箇所は20ページ程度なのでこのためだけに買うには少しお高いが、
Ruby自体に興味のある人なら買って損はない。

クラス変数

クラス変数に関しても少し足りない。これは公式リファレンスが参考になる。

https://docs.ruby-lang.org/ja/latest/doc/spec=2fvariables.html#class
https://docs.ruby-lang.org/ja/latest/doc/spec=2fvariables.html#class_var_scope

特に以下の記載が重要になると思う。

クラス変数は、その場所を囲むもっとも内側の(特異クラスでない) class 式または module 式のボディをスコープとして持ちます。

この辺りは一旦保留して、問題集を解きながら実際に行き当たったタイミングで調べるのも良いかもしれない。

学習完了時点での予想スコア

50-60点

ここで受けてもまぁ受からないよね、というレベル。

根拠:

  • 「Rubyのオブジェクトモデルに関する知識」を問う設問が全体の半分強ある
  • 恐らく無勉でも運だけで20点位は取れる(はず)

問題集を繰り返し解く(予想スコア: 70-80点)

オブジェクトモデルを押さえたらもう問題集を解きはじめて良い頃合いだ。

前述の「その他種類が多くてよくわからん」試験範囲はどうするって?
1つ1つ学習するのはめんどくさいので、実際の問題を解きながら調べながらで学んでいくことをオススメする。

この辺り種類は多いものの出題の形式は大体決まっているようだ。パターンを押さえてそこから知識を広げていく方が効率が良いだろう。(ただしその分「知識を広げる」行為は主体的に行う必要がある)

使える問題集の話

問題集は以下の3つを使えばOK。(他はあまり見つからない)

問題集はひたすら周回するのが一番手っ取り早い。
ソシャゲのマラソンみたいなノリで、ひたすら走るべし。

実際に私が用いた手順を紹介する。参考にしてほしい。

  1. RExを3回連続90点以上取れるようになるまで回す
    (RExは受ける度にある程度問題が変わるので一番オススメ!)
  2. 教本の問題を解き、100点が取れるまで繰り返す
  3. CTCをサラッと解く(この段階では恐らく容易に良い点が取れるはず)

問題集の答えを覚えてしまって困る話

問題集を繰り返すと必然的に答えを覚えてしまう。
この状態でただ漫然と問題をこなしても、本番で通用する知識を身に付けるのは難しいだろう。

そんな時に強くオススメしたいのが、
問題の背景や出題意図、回答の理由等を(頭の中なり口に出したりして)毎回説明してみる
ことだ。

問題によっては今ひとつ上手く説明できなかったり、ちょっとした疑問が浮かぶものがあると思うので、問題番号をメモっておく。後ほど徹底的に調査して、説明できる/疑問を潰す事を繰り返すと、学びの深度が増して合格に近づく。

調査のやり方としては例えば、、、

  • 問題集の解答を読む
  • ネットや書籍で調べる(特にRubyリファレンスは積極的に活用したい)
  • irb等で実際に動作を確かめる
  • 理解した内容をメモしてみる

などなど。。。

特にirb等で実際に動作を確かめると、自然と派生動作も確かめたくなるのでオススメだ。

また学んだ事を文章に落とし込むのも良い。以下のブログで紹介されている"学習メモ"が参考になる。
個人的には「なんとなく理解しているがイマイチ不安」な内容を深めるのに特に効果があった。
RubySilverに合格したので学習メモを公開

この辺りを広く深くやればやるほど、応用の効く知識が身につき、恐らく本番に強くなるだろう。

学習完了時点での予想スコア

70-80点

運がよければこの段階でも合格できるかもしれない。。。というレベル。

根拠

  • 自分の経験として、RExで3回連続90点以上取ったあと、初見の教本の模擬試験で80点を取った
    (本番はそれよりも難しいことも考慮)
  • 合格記事を数多く漁った限り、上の問題集で頻出っぽい問題を落としていても、合格点に達し得る様子

先人の残したブログで知識を補う(予想スコア: 85点以上)

この段階でも運が良ければ合格できるようにも思う。ただそれもせいぜい60%程度の確率だろう(適当)。
受験料が15000円とお高めなRuby Goldでは少し心もとない。

ここからは先人の残してくれたブログを見ながら知識を磨き上げていく。実際のところ上の問題集ではカバーしきれていない内容も多いので、確実な合格のためには欠かせないプロセスかなぁと思っている。

以下私がお世話になったブログを紹介する。これら全てを、ページ内でさらに紹介されているリンク先含めて押さえれば、本番での初見殺しを可能な限り回避できるはず。

やっぱりただ読んでるだけじゃ良くない話

上のブログを見る際も、問題集で分からない事に遭遇した時と同じように対応した方が良い。つまりただ書いてあることをなぞるのではなく、理解するために色々な手段をとり、出来れば実際に手を動かす。

また関連リンク含めるとそこそこ分量はあるので、合間に改めて問題集を解く時間を作ると多少気分が紛れる。ここまで来ていれば1回30分ちょっとで終わるだろう。ブログの内容も踏まえれば相乗効果でさらに学びが深まるはず。1日1回はいずれかの問題集を解く、というのも良さそうだ。(やった)

多分この頃にはRuby Goldの勉強にとっくに飽きて嫌になっているとは思う。私も早く終わらせたい気持ちでいっぱいだった。でももうひと踏ん張りだ。できる範囲でやってみて!

学習完了時点での予想スコア

85点以上

ある程度余裕を持って合格できる、はず。。。

根拠

  • 上のブログ全てに目を通した私が、本番で目にした完全初見の内容は2,3問程度だった。
    (もちろん運もあるとは思うが。。。)
  • 90点とった(私が)

さいごに

まぁこんだけ頑張れば受かるよ多分!受かると思いたい!

あとは試験当日に体調を崩さないように気をつけることと、当日は2種類の本人確認書類が必要になること辺りに注意して、ズバッと合格を勝ち取ってください!

改めてになるけど、予想スコアは併記した程度の薄弱な根拠しかないのであくまで参考って思っておいてね!

最後にこんなに長くなるとは思わなかった! 疲れた! なげぇよこの記事...

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby Goldに合格したので、勉強方法をまとめてみた(2020年11月版)

Ruby Silverに合格したので、勉強方法をまとめてみた(2019年2月版)
の続編。

先日Ruby Goldに合格した。90点だった。中々頑張ったと思う。
需要のほどは分からないが、忘れないうちに勉強方法をまとめてみる。

単に勉強方法を並べるだけでは面白みに欠けるので、
各学習段階における本番のスコア予想を完全な独断と偏見に基づいて示してみる。
つまり「ここまでやれば本番でこの位の点数になる気がする(無責任)」という話。

勉強の結果どのくらい合格に近づいているか?というのは、モチベ維持にも役立ちそうだと思い添えてみた。
まぁ私の感覚に基づくものなので、記事の賑やかしとして参考程度に捉えてほしい。
(メインコンテンツはあくまで勉強方法!)

とりあえず結論

  • さらっと試験範囲に目を通す(予想スコア: なし)
  • Rubyのオブジェクト指向をがっつり学ぶ(予想スコア: 50-60点)
  • 問題集を繰り返し解く(予想スコア: 70-80点)
  • 先人の残したブログで知識を補う(予想スコア: 85点以上)

前提

学習開始時点での私のRuby経歴

  • 実務で半年〜1年。(Ruby以外の言語を含めると実務トータル2年弱程度)

学習期間 & 学習時間

  • 学習期間: 2週間ちょっと
  • 学習時間: 40〜50時間(平日2,3時間、休日5時間)

本題: 勉強方法

さらっと試験範囲に目を通す(予想スコア: なし)

まずは大まかに試験範囲のイメージを掴む。
ググって出てきた合格記事を上からいくつか読み比べて、試験範囲の大まかな特徴がつかめればOK。

以下の書籍の 2〜5章でRuby Goldの試験範囲を眺めるのも良い。
[改訂2版]Ruby技術者認定試験合格教本(Silver/Gold対応)Ruby公式資格教科書

すると恐らく以下のような傾向が見えてくると思う。

  • オブジェクト指向に関する設問が全体の半分強を占める
    • 特異クラス?メソッドの継承ツリー? あとメタプログラミングRubyを読むと良いらしい?
  • 残りの半分弱は、実行環境・文法・ライブラリ等から少しずつ出題される。
    • 「これいつ使うんだろう?」って話もたくさん。。。^^;

ひとことで言えば、
「オブジェクト指向関連はガッツリ学ぶ必要があるようだが、その他は種類が多くてよくわからん」
という印象を持つだろう。

その認識は正しい。Ruby Goldの実態は大体そんな感じだ。

本記事の構成の話

ということで本記事では以降、

  • 「オブジェクト指向関連」をどうガッツリ学べば良いか?
  • 「その他は種類が多くてよくわからん」箇所をどう押さえていけば良いか?

の2点を中心に説明していく。

学習完了時点での予想スコア

なし

この時点では特に学習の成果を気にする必要はないだろう。ウォーミングアップみたいなものなので。

「オブジェクト指向関連」をガッツリ学ぶ(予想スコア: 50-60点)

前述の通り、試験問題の半数強はオブジェクト指向関連の設問になる。
まずはここを押さえるのが手堅いだろう。

Ruby Goldにおけるオブジェクト指向関連の設問は、例えば以下のような内容を含んでいる。
(本記事では便宜上これらを「Rubyのオブジェクトモデル(に関する知識)」と呼ぶ事にする)

クラスの継承・Mix-inを考慮したメソッドや定数の探索順, 特異クラス・特異メソッド・クラスメソッド, インスタンス変数(クラスインスタンス変数)・クラス変数・定数等のスコープ, etc...

読むべき本(テンプレ)の話

ではRubyのオブジェクトモデルをどのように"ガッツリ"学べば良いか?
幸いな事にこれにはもうテンプレがある。以下の書籍を読めば良い。

この2冊はRuby Goldを受けるなら可能な限り手に入れた方が良い。
(他の教材はおおよそネットで無料で手に入る)

ここがRuby Goldの山場だという話

この辺りの知識(特にメタプログラミングRuby)は一度で理解するのが難しいかもしれない。ただ、ここだけは真正面から取り組んだ方が良いし、Ruby Goldに関係なくその価値がある。繰り返し読み、関連知識をググり、できる限り手を動かす事をオススメする。内容としては教本の方が少しやさしいのでそちらから手を出すのも良いだろう。(大したアドバイスができず申し訳ない...他にも良い記事いっぱいあるのでググって...)

何度読んでも分からない場合はまだRuby Goldは少し早いのかもしれない。もう少し経験を積んで改めて挑戦することを考えてもいい。(私も以前メタプログラミングRubyを読もうとして途中で挫折した経験があったり)

逆に言えばこれ以上難しい話はRuby Goldの試験範囲には存在しない。これ以降は(めんどくさいことはあっても)全く理解できない内容は出てこないだろう。ここが山場なので気合いを入れて学習したい。

メタプログラミングRuby(1〜5章)の内容が8割程度理解でき、オブジェクト・クラス・特異クラスの関係性の図(5章の図5-5)を頭の中で思い描けるようになる辺りが学習完了の目安だろう。もしくは以下のサイトの図も理解度を測るちょうど良い目安になると思う。

「クラスはオブジェクトである」に辿り着くまで

ちょっと足りない話

実はこの2冊だけだとオブジェクトモデル関連で少し弱い点がある。軽く学習方法を紹介する。

定数探索周り

定数探索は「最初はレキシカルスコープ、見つからなかったら継承チェーン」
ということだけ覚えて少しググってほしい。
(絶対参照/相対参照辺りは一旦理解を保留しても良い。あくまで調査した範囲だが、Ruby Goldではその点をあまり問われない。全く無いとは言えないが...)

きっちりした情報がほしいという人はRubyの仕組み の第6章が参考になる。
該当箇所は20ページ程度なのでこのためだけに買うには少しお高いが、
Ruby自体に興味のある人なら買って損はない。

クラス変数

クラス変数に関しても少し足りない。これは公式リファレンスが参考になる。

https://docs.ruby-lang.org/ja/latest/doc/spec=2fvariables.html#class
https://docs.ruby-lang.org/ja/latest/doc/spec=2fvariables.html#class_var_scope

特に以下の記載が重要になると思う。

クラス変数は、その場所を囲むもっとも内側の(特異クラスでない) class 式または module 式のボディをスコープとして持ちます。

この辺りは一旦保留して、問題集を解きながら実際に行き当たったタイミングで調べるのも良いかもしれない。

学習完了時点での予想スコア

50-60点

ここで受けてもまぁ受からないよね、というレベル。

根拠:

  • 「Rubyのオブジェクトモデルに関する知識」を問う設問が全体の半分強ある
  • 恐らく無勉でも運だけで20点位は取れる(はず)

問題集を繰り返し解く(予想スコア: 70-80点)

オブジェクトモデルを押さえたらもう問題集を解きはじめて良い頃合いだ。

前述の「その他種類が多くてよくわからん」試験範囲はどうするって?
1つ1つ学習するのはめんどくさいので、実際の問題を解きながら調べながらで学んでいくことをオススメする。

この辺り種類は多いものの出題の形式は大体決まっているようだ。パターンを押さえてそこから知識を広げていく方が効率が良いだろう。(ただしその分「知識を広げる」行為は主体的に行う必要がある)

使える問題集の話

問題集は以下の3つを使えばOK。(他はあまり見つからない)

問題集はひたすら周回するのが一番手っ取り早い。
ソシャゲのマラソンみたいなノリで、ひたすら走るべし。

実際に私が用いた手順を紹介する。参考にしてほしい。

  1. RExを3回連続90点以上取れるようになるまで回す
    (RExは受ける度にある程度問題が変わるので一番オススメ!)
  2. 教本の問題を解き、100点が取れるまで繰り返す
  3. CTCをサラッと解く(この段階では恐らく容易に良い点が取れるはず)

問題集の答えを覚えてしまって困る話

問題集を繰り返すと必然的に答えを覚えてしまう。
この状態でただ漫然と問題をこなしても、本番で通用する知識を身に付けるのは難しいだろう。

そんな時に強くオススメしたいのが、
問題の背景や出題意図、回答の理由等を(頭の中なり口に出したりして)毎回説明してみる
ことだ。

問題によっては今ひとつ上手く説明できなかったり、ちょっとした疑問が浮かぶものがあると思うので、問題番号をメモっておく。後ほど徹底的に調査して、説明できる/疑問を潰す事を繰り返すと、学びの深度が増して合格に近づく。

調査のやり方としては例えば、、、

  • 問題集の解答を読む
  • ネットや書籍で調べる(特にRubyリファレンスは積極的に活用したい)
  • irb等で実際に動作を確かめる
  • 理解した内容をメモしてみる

などなど。。。

特にirb等で実際に動作を確かめると、自然と派生動作も確かめたくなるのでオススメだ。

また学んだ事を文章に落とし込むのも良い。以下のブログで紹介されている"学習メモ"が参考になる。
個人的には「なんとなく理解しているがイマイチ不安」な内容を深めるのに特に効果があった。
RubySilverに合格したので学習メモを公開

この辺りを広く深くやればやるほど、応用の効く知識が身につき、恐らく本番に強くなるだろう。

学習完了時点での予想スコア

70-80点

運がよければこの段階でも合格できるかもしれない。。。というレベル。

根拠

  • 自分の経験として、RExで3回連続90点以上取ったあと、初見の教本の模擬試験で80点を取った
    (本番はそれよりも難しいことも考慮)
  • 合格記事を数多く漁った限り、上の問題集で頻出っぽい問題を落としていても、合格点に達し得る様子

先人の残したブログで知識を補う(予想スコア: 85点以上)

この段階でも運が良ければ合格できるようにも思う。ただそれもせいぜい60%程度の確率だろう(適当)。
受験料が15000円とお高めなRuby Goldでは少し心もとない。

ここからは先人の残してくれたブログを見ながら知識を磨き上げていく。実際のところ上の問題集ではカバーしきれていない内容も多いので、確実な合格のためには欠かせないプロセスかなぁと思っている。

以下私がお世話になったブログを紹介する。これら全てを、ページ内でさらに紹介されているリンク先含めて押さえれば、本番での初見殺しを可能な限り回避できるはず。

やっぱりただ読んでるだけじゃ良くない話

上のブログを見る際も、問題集で分からない事に遭遇した時と同じように対応した方が良い。つまりただ書いてあることをなぞるのではなく、理解するために色々な手段をとり、出来れば実際に手を動かす。

また関連リンク含めるとそこそこ分量はあるので、合間に改めて問題集を解く時間を作ると多少気分が紛れる。ここまで来ていれば1回30分ちょっとで終わるだろう。ブログの内容も踏まえれば相乗効果でさらに学びが深まるはず。1日1回はいずれかの問題集を解く、というのも良さそうだ。(やった)

多分この頃にはRuby Goldの勉強にとっくに飽きて嫌になっているとは思う。私も早く終わらせたい気持ちでいっぱいだった。でももうひと踏ん張りだ。できる範囲でやってみて!

学習完了時点での予想スコア

85点以上

ある程度余裕を持って合格できる、はず。。。

根拠

  • 上のブログ全てに目を通した私が、本番で目にした完全初見の内容は2,3問程度だった。
    (もちろん運もあるとは思うが。。。)
  • 90点とった(私が)

さいごに

まぁこんだけ頑張れば受かるよ多分!受かると思いたい!

あとは試験当日に体調を崩さないように気をつけることと、当日は2種類の本人確認書類が必要になること辺りに注意して、ズバッと合格を勝ち取ってください!

改めてになるけど、予想スコアは併記した程度の薄弱な根拠しかないのであくまで参考って思っておいてね!

最後にこんなに長くなるとは思わなかった! 疲れた! なげぇよこの記事...

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】SNS認証の実装

概要

  • ユーザー管理にはdeviseを使用する。
  • SNS認証にはomniauthを使用する。

SNS認証のGemをインストール

FacebookとGoogleのomniauthとCSRF脆弱性を担保するgemをインストール。

gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'
gem "omniauth-rails_csrf_protection"

環境変数の設定

各サイトで設定したIDとKEYを環境変数に設定。

アプリ側で環境変数を読み込む

config/initializers/devise.rb
Devise.setup do |config|
  # 省略
  config.omniauth :facebook,ENV['FACEBOOK_CLIENT_ID'],ENV['FACEBOOK_CLIENT_SECRET']
  config.omniauth :google_oauth2,ENV['GOOGLE_CLIENT_ID'],ENV['GOOGLE_CLIENT_SECRET']
end

モデルの設定

モデルを作成

SnsCredentialモデルを作成し、providerとuidを保存。

sns_credentials.rb
class CreateSnsCredentials < ActiveRecord::Migration[6.0]
 def change
   create_table :sns_credentials do |t|
     t.string :provider
     t.string :uid
     t.references :user,  foreign_key: true

     t.timestamps
   end
 end
end

UserモデルとSnsCredentialモデルを編集

userモデルでOumniAuthを使用できるように編集。

user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:facebook, :google_oauth2]

UserモデルとSnsCredentialモデルのアソシエーションも設定

user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:facebook, :google_oauth2]

  has_many :sns_credentials
sns_credential.rb
class SnsCredential < ApplicationRecord
 belongs_to :user
end

deviseのコントローラーを再設定

% rails g devise:controllers users
routes.rb
Rails.application.routes.draw do
 devise_for :users, controllers: {
   omniauth_callbacks: 'users/omniauth_callbacks',
   registrations: 'users/registrations'
 }
end

SNS認証の実装

omniauth_callbacks_controllerの設定

app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

 def facebook
  authorization
 end

 def google_oauth2
  authorization
 end

 private

 def authorization
   @user = User.from_omniauth(request.env["omniauth.auth"])

   if @user.persisted? #ユーザー情報が登録済みなので、新規登録ではなくログイン処理を行う
    sign_in_and_redirect @user, event: :authentication
   else #ユーザー情報が未登録なので、新規登録画面へ遷移する
    render template: 'devise/registrations/new'
   end
 end
end

ビューの編集

new.html.erb
<%= link_to "メールアドレスで登録", new_user_registration_path%>

<%= link_to 'Facebookで登録', user_facebook_omniauth_authorize_path, method: :post%>
<%= link_to 'Googleで登録', user_google_oauth2_omniauth_authorize_path, method: :post%>

Userモデルにメソッドを追加

first_or_createは、保存するレコードがデータベースに存在するか検索を行い、検索した条件のレコードがあればそのレコードのインスタンスを返し、なければ新しくインスタンスを保存するメソッドです。
first_or_initializeは、whereメソッドとともに使うことで、whereで検索した条件のレコードがあればそのレコードのインスタンスを返し、なければ新しくインスタンスを作るメソッドです。

first_or_create 新規レコードをデータベースに保存する
first_or_initialize 新規レコードをデータベースに保存しない
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, :omniauthable, omniauth_providers: [:facebook, :google_oauth2]

 has_many :sns_credentials

 def self.from_omniauth(auth)
  sns = SnsCredential.where(provider: auth.provider, uid: auth.uid).first_or_create
 # sns認証したことがあればアソシエーションで取得
  # 無ければemailでユーザー検索して取得orビルド(保存はしない)
  user = User.where(email: auth.info.email).first_or_initialize(
   nickname: auth.info.name,
   email: auth.info.email
  )
  # userが登録済みであるか判断
   if user.persisted?
     sns.user = user
     sns.save
   end
   user
 end
end

SNS認証時にはパスワード入力を不要に

アソシエーションにオプションを付ける

optional: true とは、レコードを保存する際に、外部キーの値がない場合でも保存ができるオプションです。

sns_credential.rb
class SnsCredential < ApplicationRecord
 belongs_to :user, optional: true
end

Userモデルを編集

SNS認証を行ったかの判断をするために、snsに入っているsns_idをビューで扱えるようにするため、コントローラーに渡します。

user.rb
class User < ApplicationRecord
 devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:facebook, :google_oauth2]

 has_many :sns_credentials

 def self.from_omniauth(auth)
   sns = SnsCredential.where(provider: auth.provider, uid: auth.uid).first_or_create
   # sns認証したことがあればアソシエーションで取得
   # 無ければemailでユーザー検索して取得orビルド(保存はしない)
   user = User.where(email: auth.info.email).first_or_initialize(
     nickname: auth.info.name,
       email: auth.info.email
   )
   # userが登録済みの場合はそのままログインの処理へ行くので、ここでsnsのuser_idを更新しておく
   if user.persisted?
     sns.user = user
     sns.save
   end
   { user: user, sns: sns }
 end
end

コントローラーを編集しましょう

Userモデルから送られたデータをビューで扱えるようにします。
@Userには「nickname」と「email」の情報をもたせて、SNS認証の判断はsns_idで行う為、idだけビューで扱えるようにします。

app/controllers/users/omniauth_callbacks_controller.rb
Class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
 #中略
 def authorization
   sns_info = User.from_omniauth(request.env["omniauth.auth"])
   @user = sns_info[:user]

   if @user.persisted?
     sign_in_and_redirect @user, event: :authentication
   else
     @sns_id = sns_info[:sns].id
     render template: 'devise/registrations/new'
   end
 end
end

ビューを編集しましょう

ビューでは、SNS認証を行っているか、行っていないかの条件分岐を記述します。
このparamsは通常devise/registrations#createアクションへ送信されますが、今回はこのコントローラーを上書きするためにcontrollers/users/registrations_controller.rbを作成してあります。
このコントローラー内でcreateアクションの動作を変更しましょう。

app/views/devise/registrations/new.html.erb
 <div class="field">
    <%= f.label :birthday %><br />
    <%= f.date_select :birthday, start_year: 1950, end_year: 2019 %>
  </div>

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

 <%if @sns_id.present? %>
   <%= hidden_field_tag :sns_auth, true %>
 <% else %>
   <div class="field">
     <%= f.label :password %>
     <% @minimum_password_length %>
     <em>(<%= @minimum_password_length %> characters minimum)</em>
     <br />
     <%= f.password_field :password, autocomplete: "new-password" %>
   </div>

   <div class="field">
     <%= f.label :password_confirmation %><br />
     <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
   </div>
 <% end %>
#中略
<% end %>

コントローラーを編集しましょう

createアクションのコメントアウトを外して編集します。
rubyでは継承先のクラスでsuperメソッドを使うことで親モデルの同名メソッドをそのまま実行します。ここではdevise本来のregistrations#createアクションが実行されるということです。今回の親モデルは、Userモデルに紐付いているdeviseになります。
params[:sns_auth]を取得した時だけDevise.friendly_tokenを使ってパスワードを自動生成し、あとの処理はsuperメソッドでdeviseのregistrations#createを実行させて完成です。

app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
 # before_action :configure_sign_up_params, only: [:create]
 # before_action :configure_account_update_params, only: [:update]


 # GET /resource/sign_up
 # def new
 #   super
 # end

 # POST /resource
 def create
   if params[:sns_auth] == 'true'
     pass = Devise.friendly_token
     params[:user][:password] = pass
     params[:user][:password_confirmation] = pass
   end
   super
 end
#省略
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSで80ポートを開いてるのに【このサイトにアクセスできません】が出る

image-2.png

先日Railsアプリをsslで通信したいと考えRailsでconfig.force_sslを設定してからなぜかアプリが表示されなくなったため、その時の対処法をまとめました。

アプリの状態

アプリ名 my-app
server EC2
web server nginx
application server unicorn
解放ポート 80, 443, 22

まずはセキュリティグループを確認

いつものことかと思い

AWS→セキュリティグループ→対象のパブリックなセキュリティグループを確認

しかし特に異常は見つからず80番と443番はしっかり開いてました。
普通なら通信はできるはずなのですが…

ちなみにlocal環境からEC2インスタンスへssh通信はできているようです。

nginxが80ポートにlistenしているかを確認

続いてnginxの設定ファイルを確認し80ポートにlistenされているか。

$ssh USER@MY-ELASTIC-IP

$ cat /etc/nginx/conf.d/my-app.conf


upstream unicorn {
          server unix:/var/www/my-app/shared/tmp/sockets/unicorn.sock;
}
server {
  listen 80; <-----------
  server_name ELASTIC-IP;
  root /var/www/my-app/current/public;

  access_log /var/log/nginx/nginx_access.log;
  error_log  /var/log/nginx/nginx_error.log;


  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://unicorn;
  }
}

ポート指定も問題ないようです。

コンソールからポートが開いているかチェック

$ netstat -tln

# 接続しているものでlisten済みのものを表示

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 :::3306                 :::*                    LISTEN
tcp6       0      0 :::111                  :::*                    LISTEN

確認してみると確かに接続を許していないようです。なぜ22ポートだけが開いているのかわかりません。

試しにこの状態でセキュリティグループをいじくっても結果は変わらず…

セキュリティグループの他にもネットワークインターフェースやネットワークACL、インターネットゲートウェイ、ルートテーブルなども確認してみたのですが結果は変わりませんでした、

結論 ngixnの不調でした

結局nginxを調べてみることに。
すると…

$ sudo nginx -s reload

----------------------------------------------------------------------

nginx: [error] open() "/var/run/nginx.pid" failed (2: No such file or directory)

capistranoでデプロイした際は特に問題なくunicornは起動していたので見落としてしまっていましたがここに原因があったようです。

nginxpidファイルが消失してしまっていたため作り直します。

ngixn 再起動

$ sudo service nginx stop

$ sudo touch /run/nginx.pid     

$ nginx -t

$ sudo service ngixn start  

再び確認

$ sudo service ngix status

----------------------------------------------------------------------
Redirecting to /bin/systemctl status nginx.service
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2020-10-30 06:05:36 UTC; 3h 28min ago
  Process: 22103 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
  Process: 22100 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 22099 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 22106 (nginx)
   CGroup: /system.slice/nginx.service
           ├─22106 nginx: master process /usr/sbin/nginx
           └─22111 nginx: worker process

Oct 30 06:05:36 ip-10-0-0-178.us-east-2.compute.internal systemd[1]: Starting The nginx HTTP and reverse proxy server...
Oct 30 06:05:36 *p-10-0-0-178.us-east-2.compute.internal nginx[22100]: nginx: the configuration file /etc/nginx/ngi...ok
Oct 30 06:05:36 ip-10-0-0-178.us-east-2.compute.internal nginx[22100]: nginx: configuration file /etc/nginx/nginx.c...ul
Oct 30 06:05:36 ip-10-0-0-178.us-east-2.compute.internal systemd[1]: Failed to read PID from file /run/nginx.pid: ...ent
Oct 30 06:05:36 ip-10-0-0-178.us-east-2.compute.internal systemd[1]: Started The nginx HTTP and reverse proxy server.
Hint: Some lines were ellipsized, use -l to show in full.

その後

$ netstat -tlnt

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 :::3306                 :::*                    LISTEN
tcp6       0      0 :::111                  :::*                    LISTEN
tcp6       0      0 :::80                   :::*                    LISTEN

解決しました!

nginxが上手く機能していないとすると80ポートが閉じてしまうのは知らなかったですね…

原因はおそらくインスタンスの再起動

rails で config.force_ssl = trueを使用

sslに必要な設定を行っていなかったため表示エラー

その際EC2インスタンスを再起動したため上手くnginxが機能していなかったのだと思います。

config.force_sslエラーについてはこちらの記事にまとめました。
>>【config.force_ssl】を使用したらページが表示されなくなった

次回同じようなエラーに遭遇したらまずはnginxからポートが開いているかを確認してからawsコンソールを弄ろうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

インデントを意識して綺麗なコードを書こう(rails,html)

コードを書いていく上でインデント(段落)を意識することはとても重要です。
綺麗なコードはエラー数を減らすことはもちろん、エラー時の解決速度、コードの見返しやすさなど多くのことに貢献します。
ここでは綺麗なコードを書く上で大事なインデントを説明していこうと思います。
ではrailsについて、気をつけるべき点はif文、def、each文ですね!!
最初にif文を書いていきます!

#分かりやすいコード
if @tweet.save
  redirect_to("/")
else
  redirect_to("/new")
end

#分かりにくいコード
if @tweet.save
redirect_to("/")
else
redirect_to("/new")
end

ここで大事な点は、ifとendで囲まれた部分はインデントを落とすことで(2文字分開けることで)どこにif文が適応されているかが非常にわかりやすい!!!と言うこと。
注意して書いて欲しいところです!

次にeach文(繰り返し処理)について 実際の例を見ていきましょう!

#分かりやすいコード
<% @tweets.each do |t| %>
  <%= t.body %>
<% end %>

#分かりにくいコード
<% @tweets.each do |t| %>
<%= t.body %>
<% end %>

これも上の例と言いたいことは一緒ですね!!!
何かとendで囲まれている部分は二文字分、もしくはtabキー1つ分落とすことでどこを繰り返すかわかりやすいってことですね!!
さて次の例は、、、defです!!

#分かりやすいコード
def index
  @tweets = Tweet.all
  @user = User.find(params[:id])
end

#分かりにくいコード
def index
@tweets = Tweet.all
 @user = User.find(params[:id])
end

もう、しつこいですよね笑 でも大事なことなんで言わせていただきます! def each if などとendで囲まれた部分はインデントを絶対に意識しましょう!

最後にもう一つ、htmlのタグ(div)のインデントについて学んでいきましょう!
実際に見ていくのがいいですね!

<!-- 分かりやすいコード -->
<div class="allContainer">
  <div class="container">
    <p>インデントは大事</p>
  </div>
</div>

<!-- 分かりにくいコード -->
<div class="allContainer">
<div class="container">
<p>インデントは大事</p>
</div>
</div>

もはや閉じタグ()がどのようにかかっているか分かりにくいですよね??
なのでdivの個数などを間違えてしまうなどのミスが起き、うまく思うように実行されないエラーも出てきます。

以上のように
・インデントってのはめちゃくちゃ大事!!
・これができるだけでめっちゃ綺麗なコードになる!!

ので、これから一個ずつ注意して書いていきましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

学習アウトプット〜11/3〜

生成したコードを元に戻す方法

「ああ、あの頃に戻れればなあと」自分の人生のある地点の後悔を引きずっている人は多いと思います。私にもそのような後悔はあります。

でも人生は元には戻れません。今に目を向けましょう。周りにいる人を見てみてください。その人たちと一緒に今を必死に生きていきましょう。

ということで、人生は元には戻せませんが、プログラミングは別です。
何か間違いがあれば何度でもやり直せます。笑

コントローラ

$ rails geneate controllar motipuyo

というようにmotipuyoという名前のコントローラを作成したけど、無かったことにしたいよって時は

$ rails destroy controllar motipuyo

で削除されます。

コントローラは学校で言うとクラスの担任です。
modelやviewに指示を出すことで各クラスをまとめ、アプリケーションという一つの学校を成り立たせる。
今のところはこのようなイメージです笑。

データベース

$ rails db:migrate

上記はrailsのデータベースをマイグレイト(移行する、新しく更新する的な意味)するコマンドですが、それを取り消したい時は、

$ rails db:rollback
$ rails db:migrate VERSION=0

というコマンドを使うと削除できます。

上の"rollback""コマンドは一つ前に戻したい時、
下の"VERSION=0"のコマンドは最初の状態に戻したい時に使用します。

今は理解が難しいですが、
データベースを"migrate"で更新していくのを"rollback"で戻ることができる、
という程度に理解しておきます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rubyの復習

本投稿の目的

Rubyの復習の自分用の議事録です。
以前,inputした知識のうち忘れたことを羅列して書いていきます。
そのため,自己満で書いただけなので脳に叩き込めたら消す予定です。


学習に使った教材

Udemyの "はじめてのRuby on Rails入門-RubyとRailsを基礎から学びWebアプリケーションをネットに公開しよう" を教材として使用しました。

購入目的は以下の2つです。
①Cloud9上でRailsアプリを作ること
②デプロイすること


①配列とハッシュ

○配列

qiita.rb
a = [変数1,変数2,変数3]

・添字は0から始まる
・変数2を取り出すには a[1]

○空判定

qiita.rb
a.empty

⇨判定が空なら true

○検索文字判定

qiita.rb
a.include?('検索文字')

⇨検索文字を配列に含む場合はtrueを返す

○連続値の配列への格納

qiita.rb
aa = (0..100).to_a

⇨指定したn個以上の情報を配列に格納

○配列への操作

qiita.rb
配列名.pop
配列名.shift
配列名 << 
配列名.join (' ')
配列名.sort!.reverse!

上から順に
・一番最後の値を消去
・一番最初の値を消去
・一番最後に値を追加
・添字ごとに空白一個あけで結合
・配列の中身を反対にする

○ハッシュ

キーを指定することで,2変数の配列を作れる

qiita.rb
ハッシュ = {キー1 => 1,キー2 => 2,キー3 => 3}
qiita.rb
puts ハッシュ['キー1']
ハッシュ['キー4'] = 4
ハッシュ['キー1'] = 1
ハッシュ.delete('キー1')     

上から順に
・値の取り出し
・値の追加
・値の上書き
・値の削除

○シンボル

ソースコード 上では文字列
内部では整数として扱われる
⇨ハッシュ内部のアクセスが早くなる

qiita.rb
ハッシュ = {キー1 : 1,キー2 : 2,キー3 : 3}
qiita.rb
puts ハッシュ[:キー1]   
ハッシュ[:キー4] = 4  
ハッシュ[:キー1] = 1`     
ハッシュ.delete(:キー1)      
ハッシュ.has_key?(:探したいキーn)  
ハッシュ.size                                         

上から順に
・値の取り出し
・値の追加
・値の上書き
・値の削除
・探したいキーを持っているか?確認
・いくつキーを持つか?確認

②each配列とeachハッシュ

○each配列

qiita.rb
numbers = [1,2,3,4,5]
numbers.each do |number|

<別の記載方法>
numbers = [1,2,3,4,5]
numbers.each { |number| puts number}

○eachキャッシュ

qiita.rb
scores = {luke: 100,jack: 90,robert: 70}
scores.each do |k,v|
     puts v
     puts "#{k},#{v}"
end

③クラス作成

qiita.rb
class Car
  def initialize(name)
    puts 'initialize'
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}."
  end
end

boxter = Car.new('boxter')
boxter.hello

carrera = Car.new('carrera')
carrera.hello

【解説】
・class作成時の変数は1文字目は大文字
・インスタンス作成時に指定した引数をinitialzeの戻り値に指定できる
・インスタンス作成 とは,クラスを動かす際のcloneの作成のようなもの
 ⇨宣言時は 変数 = クラス名.new()
・def initialize はインスタンス作成時に実行される処理
・インスタンス変数は,initialize内で定義した@変数
 ⇨Class内でどこでも使用可能

④インスタンスメソッド

qiita.rb
class Car

  def initialize(name)
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}."
  end
end

def name
  @name
end

def name = (value)
  @name = value
end

boxter = Car.new('boxter')
boxter.hello
boxter.name
boxter.name = '718boxter'
puts boxter.name

【解説】
・def name部分がない場合,class外から@nameへアクセスできない
(インスタンス変数(@name)はクラス外からアクセスできない)
・ インスタンス作成後の.nameメソッドを実行したことでアクセス可能
・.nameメソッドに対応する値@nameを取得可能
・これらを'インスタンスメソッド'と呼ぶ(ゲッターメソッド)

・def nama = (value) について
⇨インスタンス作成後にboxter.name = 'boxter' とすることで
@name に任意のvalueを指定可能.それを出力も可能
(ruby特有の記述方法)

⑤アクセサメソッド

qiita.rb
def name
  @name
end

def name = (value)
  @name = value
end

を全て

qiita.rb
attr_accessor :name 

で実現可能

attr_accessorメソッド
⇨自作インスタンスメソッドを開発者が書かなくて良い方法
 (他言語ではプロパティーと呼ぶ)

【読み込みのみ実行する場合】

qiita.rb
attr_reader :name 

def name 部分を1行で記述可能
@nameをただ拾うことができる

【書み込みのみ実行する場合】

qiita.rb
attr_writer :name 

def name = (value) 部分を1行で記述可能
@nameへの書き込みおのみができる

⑥クラス変数

qiita.rb
class Car
  @@count
  def initialize(name)
    puts 'initialize'
    @name = name
    @@count += 1
  end

  def self.info
    puts "Test"
  end

  def hello
    puts "Hello! I am #{@name}."
  end
end

・Class内で使用する変数
・開始文字は@@2文字から始まる
・def ごとにリセットされたくない変数を扱う時に必要な変数
⇨インスタンス生成回数をcountしたい時などに有効
⇨メソッドの実行回数をcountしたい時などに有効

⑦クラスメソッド

クラスから直接呼び出せるメソッド

qiita.rb
class Car
  def initialize(name)
    puts 'initialize'
    @name = name
  end

  def self.info
    puts "Test"
  end

  def hello
    puts "Hello! I am #{@name}."
  end
end

Car.info
boxter = Car.new('boxter')
boxter.hello

carrera = Car.new('carrera')
carrera.hello

【解説】
・self.メソッド名 としてメソッドを記述する
・Car.info のようにインスタンス生成なしで使用可能なメソッド
・通常のメソッドなら boxter.info としないと使えないはず


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

投稿したものを日付の新しい順に表示したい

何かしらの投稿機能、例えばTwitterのような新しい投稿が先に表示される機能を実装していたところ、考え方が凝り固まっていた部分があったので備忘として記載します。

私がやりそうになったのは以下です。
ハッシュを含む配列に対し、受け取った側で降順ソートして表示しようとした

しかしよく考えると、これは保守性が高くないことに気付きました。
表示は表示という機能に集中することなど、各機能はそれぞれに特化すべきです。メソッドも同様です。
そのため、受け渡す際にソートした状態で受け渡す、これを行う必要がありました。

以下は例です。
Itemテーブルに存在するデータを@itemsに格納する際、「.order('created_at DESC')」というオプションを追加しました。

controller
  def index
    @items = Item.includes(:user).order('created_at DESC')
  end

こうすることで、ビューファイルの表示、という機能に手を加えることなく制御することができました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】投稿したものを日付の新しい順に表示したい

何かしらの投稿機能、例えばTwitterのような新しい投稿が先に表示される機能を実装していたところ、考え方が凝り固まっていた部分があったので備忘として記載します。

私がやりそうになったのは以下です。
ハッシュを含む配列に対し、受け取ったビューファイル側で降順ソートして表示しようとした

しかしよく考えると、これは保守性が高くないことに気付きました。
表示は表示という機能に集中することなど、各機能はそれぞれに特化すべきです。メソッドも同様です。
そのため、受け渡す際にソートした状態で受け渡す、これを行う必要がありました。

以下は例です。
Itemテーブルに存在するデータを@itemsに格納する際、「.order('created_at DESC')」というオプションを追加しました。

controller
  def index
    @items = Item.includes(:user).order('created_at DESC')
  end

こうすることで、ビューファイルの表示、という機能に手を加えることなく制御することができました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Basic認証導入時、Heroku上でログインができない。

スクリーンショット 2020-11-04 17.42.50.png

背景

Basic認証を導入して、必要最低限のセキュリティを設けたい。
過去に2度Basic認証の練習として導入したことがあり、その時はスムーズにできたため、今回も導入したいと考えた。
しかし、実際に導入してみると、ローカル環境では正常に動作しログインできるものの、本番環境では正しいユーザー名とパスワードでも弾かれてしまった。

行ったこと

まず、現状を確認するため、もう一度git push heroku masterでどう表示されるかを確認した。

% git push heroku master
Everything up-to-date

全て最新の状態であることから環境変数を設定する前に、github上でコミットしてしまったり、git push heroku masterなどのコマンドを実行したと仮説を立てた。空のコミットをしてから、再度git push heroku masterをする必要があると考え、実行した。

% git commit --allow-empty -m "コミット名"

% git push heroku master
しかし、ログインできませんでした。

原因

application_controller.rbに記述している、private内の記述と、heroku上に設けた環境変数の名前が一致していなかった。

app/controllers/application_controller.rb
  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]
    end
  end
% heroku config

=== アプリ名 Config Vars
BASIC_AUTH_PASSWORD:      *****
BASIC_AUTH_USERNAME:      *****

対処法

双方の環境変数が紐付くように、同じ名前に変えてあげれば良い。
今回の場合はUSERNAMEかUSERに統一させてHerokuに上げれば、正常にログインできました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

マルチスケールシミュレーション特論 第7回

shebang

#!/usr/bin/env ruby

chmod

私はは emacs の設定ファイルに以下を追加することで、シェバンのあるファイルの保存時に、ファイルが executable になるように設定している

(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)

path

export PATH="$PATH:$HOME/bin"

ruby

ref: https://docs.ruby-lang.org/ja/index.html

学習内容

  • if, elsif, else, end
if year % 400 == 0
  p true
elsif year % 100 == 0
  p false
elsif year % 4 == 0
  p true
else
  p false
end
  • array, each
[2004, 1999, 1900, 2000].each do |year|
  p year
  leap?(year)
end
  • ARGV[0].to_i で文字列から整数に変換できる

  • source ~/doc/lecture/multi-scale/grad_members_20f/members/yukiue/docs/07.org
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RubyのThread#[]=メソッドの注意点

RubyのThread#[]=メソッドについて

RubyのThread#[]= メソッドでは、スレッドごとに固有の値を保持することができます。(JavaでいうThreadLocal のようなものです)
これを利用すると、1スレッド1リクエストに紐づくアプリケーションサーバ(Passengerなどほぼ全てのAPサーバ)では、
1リクエスト中のみ閉じて使用できるスレッドローカル変数として使用することができます。

RubyのThread.current[]メソッドの使用例

以下のように Thread.current[:foo] と現在のスレッドに代入することで、スレッドローカル変数 foo を定義できます。

def self.foo
  Thread.current[:foo] ||= 0
end

また、Ruby on Railsフレームワークにレコードの操作者(作成者、更新者、削除者)を記録する機能を提供するRecordWithOperatorという gem においても
この Thread#[]= を使用して実装されています。
https://github.com/nay/record_with_operator/blob/4389d077b0303b956cc211ef439a46a216ae2cc0/lib/record_with_operator/operator.rb#L4

Thread#[]=メソッドの注意点

PassengerやPumaのような一度作成したスレッドを再利用するようなアプリケーションサーバを使用している場合、
スレッドローカル変数が再利用前提のスレッドに紐づくため、アプリケーション側で明示的に破棄しないと
以前のリクエスト(スレッド)で定義した変数が別のリクエストで参照できてしまうので注意が必要です。

Redmineにも以前、Thread#[]= を使用して現在のユーザを扱うコードがあり、
エラーメッセージに別ユーザの名前が表示されるセキュリティ的なバグの発生事例がありました。
http://www.redmine.org/issues/16685

解決策

アプリケーション側で明示的にThread.currentの値を破棄することで回避できます。
RequestStoreというgemを使用すると Rack::Middlewareの層で、リクエスト毎に
Thread.current の値をクリアするようになります。

使用例は以下の通りです:

def self.foo
  RequestStore.store[:foo] ||= 0
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

unicode正規表現サンプル

unicode正規表現サンプル

毎回調べるのが面倒なので、自分が使いそうなunicode正規表現を記事にしておく...

概要 unicode正規表現
漢字ひらがな \u30a0-\u30ff\u3040-\u309f\u3005-\u3006\u30e0-\u9fcf
全角スペース \u3000
全角アルファベット大文字 \uFF41-\uFF5A
全角アルファベット小文字 \uFF21-\uFF3A
全角数字 \uFF10-\uFF19

参考

https://www.tamasoft.co.jp/ja/general-info/unicode.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rubyのversionは.rbenv/versionファイルで管理されている

.rbenv/version

.rbenv/version ファイルには、現在使用しているruby versionが記述されており、
rbenv global x.x.x コマンドなどでversionを変更すると、.rbenv/versionの内容も書き換えられる。

[ec2-user@al1-gemlist ~]$ ruby -v
ruby 2.5.7p206 (2019-10-01 revision 67816) [x86_64-linux]
[ec2-user@al1-gemlist ~]$ cat .rbenv/version
2.5.7
[ec2-user@al1-gemlist ~]$ rbenv global 2.5.8
[ec2-user@al1-gemlist ~]$ ruby -v
ruby 2.5.8p224 (2020-03-31 revision 67882) [x86_64-linux]
[ec2-user@al1-gemlist ~]$ cat .rbenv/version
2.5.8

.rbenv/version を編集するとどうなるか

それでは、逆に .rbenv/versionの方をviで編集するとどうなるか。
試しに、今現在.rbenv/version の中身を2.5.8 から2.5.0に変更してみる。

[ec2-user@al1-gemlist ~]$ sudo vi .rbenv/version
[ec2-user@al1-gemlist ~]$ cat .rbenv/version
2.5.0
[ec2-user@al1-gemlist ~]$ ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]

rubyのversionがファイルの内容に従って変更されているのが分かる。
また、rbenv versionsコマンドで確認してみると、

[ec2-user@al1-gemlist ~]$ rbenv versions
  system
* 2.5.0 (set by /home/ec2-user/.rbenv/version)
  2.5.1
  2.5.2
  2.5.3
  2.5.4
  2.5.5
  2.5.6
  2.5.7
  2.5.8
  2.6.2

こちらに関しても2.5.0になっている事が確認できる。

疑問点

しかし、ここで一つ疑問があります。
version確認コマンド上ではrubyのversionは2.5.0と表示されているのは分かったが、「内部的にも2.5.0に変更されているのであろうか」という事です。

確認方法として、opensslというgemのversionを確認します。
このgemは
rubyが2.5.8の場合2.1.2
rubyが2.5.0の場合2.1.0 となります。
(詳しくは、こちらを参照)

つまり、opensslのversionが2.1.0であれば、内部的にもruby versionが2.5.0に変更されていると言えます。

結果

[ec2-user@al1-gemlist ~]$ gem list openssl

*** LOCAL GEMS ***

openssl (default: 2.1.0)

従って、内部的にも変更出来ていることが確認出来ました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails new を実行するとbundle installの箇所でフリーズする

タイトルの通りで以下のようなエラーが表示される

Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from https://rubygems.org/
Could not fetch specs from https://rubygems.org/

このエラーが起きる要因は、Free wi-fiを使っていたり、ウィルスバスターによってよく起きるようです。

この場合自動で他のライブラリとの連動ができていない可能性があるので、手動で整えていく必要があります。

それでは以下の手順で実行していきましょう。

rubygemsのapiを確認する

% host api.rubygems.org

これを実行すると以下の内容が表示されます。

------------ここから------------
rubygems.org has address XXX.XXX.XXX.XX
rubygems.org has address XXX.XXX.XXX.XX
rubygems.org has address XXX.XXX.XXX.XX
rubygems.org has address XXX.XXX.XXX.XX
-----------ここまで使う-----------
rubygems.org has IPv6 address 2a04:4e42::70
rubygems.org mail is handled by 10 mxa.mailgun.org.
rubygems.org mail is handled by 10 mxb.mailgun.org.

XXX.XXX.XXX.XXの部分がapiの部分で様々な数字が並んでいるかと思います。この部分を使っていきます。

上記apiを使ってパスを通す

以下のファイルを開く

% sudo vim /etc/hosts

ここからパスを通していくので、先ほどの上記XXX.XXX.XXX.XX(api)を一つコピーしては、以下のように追加していく

XXX.XXX.XXX.XXX   rubygems.org
XXX.XXX.XXX.XXX   rubygems.org
XXX.XXX.XXX.XXX   rubygems.org
XXX.XXX.XXX.XXX   rubygems.org

このあとにbundle installを実行したところ解決しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails で画像アップロード実装

参考資料

carrierwaveuploader/carrierwave

画像(複数)アップロードにCarrierWaveを使ったRspec - Qiita

【Rails】複数画像を保存したい時のcarrierwaveとMiniMagickの導入 - Qiita

導入編

gem 'carrierwave', '~> 2.0'

bundle install した後、アップローダーの作成

be rails g uploader Images

app/uploaders/images_uploader.rb が作成される。

中身

class ImagesUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  # include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url(*args)
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  # Process files as they are uploaded:
  # process scale: [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end

  # Create different versions of your uploaded files:
  # version :thumb do
  #   process resize_to_fit: [50, 50]
  # end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  # def extension_whitelist
  #   %w(jpg jpeg gif png)
  # end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end
end

Image テーブルに images カラム追加。(Image テーブル作成時に Post テーブルとの紐付け済み)

複数アップロードする場合、json 形式で保存するらしいので、指定しておく。

be rails g migration add_images_to_image images:json

migrate 中身

class AddImagesToImage < ActiveRecord::Migration[6.0]
  def change
    add_column :images, :images, :json
  end
end

rails db:migrate してカラムを追加

テストの実装

models/image.rb

class Image < ApplicationRecord
  belongs_to :post
  validates :images, presence: true

  mount_uploaders :images, ImagesUploader
end

spec/factories/images.rb

FactoryBot.define do
  factory :image do
    images { [ Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/test.jpg'), 'spec/fixtures/test.jpg') ] }
    post
  end
end

spec ディレクトリ下に fixtures ディレクトリを作成。test.jpg を疑似的に作成し入れてます。

spec/models/images.rb

require "rails_helper"

RSpec.describe Image, type: :model do
  let(:pic_path) { Rails.root.join('spec/fixtures/test.jpg') }
  let(:pic) { Rack::Test::UploadedFile.new(pic_path) }

  context "画像が指定されれば" do
    it "画像がアップロードされる" do
      image = create(:image)
      expect(image).to be_valid
    end

    it "画像(複数)でもアップロードされる" do
      image = create(:image, images: [pic, pic])
      binding.pry
      expect(image).to be_valid
    end
  end

  context "画像が指定されていないと" do
    it "エラーになる" do
      image = build(:image, images: nil)
      expect(image).to be_invalid
      expect(image.errors.messages[:images]).to eq ["can't be blank"]
    end
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】MySQLによる開発

今までいくつかWebアプリケーションを制作したり学習をしてきましたが、
全てDBはデフォルトのSQLiteを使用してきました。

今回新しくアプリケーションを制作する上で本番環境をAWSにしようとするとMySQLの設定が必要・・・
ということで、MySQLを使用したいと思います!
まだまだ初心者なので、間違っているところがあればご指摘お願いします。

MySQLとは

世界で最も利用されているデータベースで、以下のような特徴があります。

  • 大容量のデータベースを高速かつ安定的に利用できる
  • 関連のあるデータ項目が、事前に定義されている
  • データベースは、テーブル単位にデータを保持し、テーブル間の関係も保持する
  • データ項目は列として表現され、関連のあるデータ項目の集合体が行として表現されたテーブルが形成される(Excelのタイトル付きの表のようなイメージ)
  • リレーショナルデータベースとのやりとりには、SQLが使用される
  • 日本語に対応している

SQLiteとの違い

Railsをインストールして、デフォルトで使用されるRDBMSはSQLite
SQLiteは以下のような特徴がある

  • それほど大きなデータベースではなく、個人利用レベルのデータベースの利用を想定している
  • リレーショナルデータベースとのやりとりには、SQLが使用される
  • 著作権が放棄されパブリックドメインで誰もが自由に利用できる
  • 消費メモリも少ないため、処理能力が低い小型デバイスでも組み込める

巨大なDBを扱う場合はMySQLを使用した方が良いらしい

MySQLで開発をしてみる

RailsはデフォルトではSQLiteを使用するため、
MySQLを使用するためには立ち上げの際に指定してあげる

rails new アプリケーション名 --database=mysql

省略もできる

rails new アプリケーション名 -d mysql

こうすることで、RDBMSをMySQLに変更することができるらしい。
念のためGemfileを確認・・・
指定しない場合は

Gemfile
# Use sqlite3 as the database for Active Record
gem 'sqlite3'

となるのに対して、指定してあげると

Gemfile
# Use mysql as the database for Active Record
gem 'mysql2', '>= 0.3.18', '< 0.5'

となりました!!

しかし、問題が・・・。
rails new アプリケーション名 -d mysqlをした段階でエラーが発生。。。

・
・
(たくさんのログ)
・

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2
/Users/mariko/.rbenv/versions/2.6.5/bin/ruby -I /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/2.6.0 -r ./siteconf20201104-33105-i9fwuc.rb extconf.rb
checking for rb_absint_size()... yes
checking for rb_absint_singlebit_p()... yes
checking for rb_wait_for_single_fd()... yes
-----
Using mysql_config at /usr/local/opt/mysql@5.7/bin/mysql_config
-----
checking for mysql.h... yes
checking for errmsg.h... yes
checking for SSL_MODE_DISABLED in mysql.h... yes
checking for SSL_MODE_PREFERRED in mysql.h... yes
checking for SSL_MODE_REQUIRED in mysql.h... yes
checking for SSL_MODE_VERIFY_CA in mysql.h... yes
checking for SSL_MODE_VERIFY_IDENTITY in mysql.h... yes
checking for MYSQL.net.vio in mysql.h... yes
checking for MYSQL.net.pvio in mysql.h... no
checking for MYSQL_ENABLE_CLEARTEXT_PLUGIN in mysql.h... yes
checking for SERVER_QUERY_NO_GOOD_INDEX_USED in mysql.h... yes
checking for SERVER_QUERY_NO_INDEX_USED in mysql.h... yes
checking for SERVER_QUERY_WAS_SLOW in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_ON in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_OFF in mysql.h... yes
checking for my_bool in mysql.h... yes
-----
Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
-----
-----
Setting libpath to /usr/local/opt/mysql@5.7/lib
-----
creating Makefile

current directory: /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2
make "DESTDIR=" clean

current directory: /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2
make "DESTDIR="
compiling client.c
compiling infile.c
compiling mysql2_ext.c
compiling result.c
compiling statement.c
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3 for inspection.
Results logged to /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-19/2.6.0/mysql2-0.5.3/gem_make.out

An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  mysql2
         run  bundle binstubs bundler
Could not find gem 'mysql2 (>= 0.4.4)' in any of the gem sources listed in your Gemfile.
         run  bundle exec spring binstub --all
Could not find gem 'mysql2 (>= 0.4.4)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.
       rails  webpacker:install
Could not find gem 'mysql2 (>= 0.4.4)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.

とりあえず翻訳してみる
「mysql2(0.5.3)のインストール中にエラーが発生し、Bundlerを続行できません。」
・・・わからない・・・。
とりあえずやっつけないと・・・!

解決方法

とりあえずログに書いてあることを実行

$ gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'

ERROR:  While executing gem ... (OptionParser::InvalidArgument)
    invalid argument: --source https://rubygems.org/

Mac へ MySQL をインストール

MySQLをインストールするという部分をすっかり見落としていました。
下記記事を参考にインストール!
Mac へ MySQL を Homebrew でインストールする手順

下記コマンドでインストール

$ brew update
$ brew install mysql

インストールができているか確認

$ brew info mysql

mysql: stable 8.0.22 (bottled)
Open source relational database management system
https://dev.mysql.com/doc/refman/8.0/en/
Conflicts with:
  mariadb (because mysql, mariadb, and percona install the same binaries)
  percona-server (because mysql, mariadb, and percona install the same binaries)
/usr/local/Cellar/mysql/8.0.22 (294 files, 296.5MB) *
  Poured from bottle on 2020-11-04 at 13:55:11
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/mysql.rb
License: GPL-2.0
==> Dependencies
Build: cmake ✘
Required: openssl@1.1 ✔, protobuf ✔
==> Caveats
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To have launchd start mysql now and restart at login:
  brew services start mysql
Or, if you don't want/need a background service you can just run:
  mysql.server start
==> Analytics
install: 85,249 (30 days), 214,834 (90 days), 813,126 (365 days)
install-on-request: 83,371 (30 days), 209,508 (90 days), 784,193 (365 days)
build-error: 0 (30 days)

バージョン8.0.22がインストールされていた!

MySQLを起動してみる

$mysql.server start
Starting MySQL
 SUCCESS! 

接続して動作確認をしてみる

$mysql -uroot

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

・・・・またまたエラー(泣)
パスワードがないからダメのか?と思い、とりあえず設定します。

セキュリティ設定

$mysql_secure_installation

Enter password for user root:(パスワードを入力する)

パスワードの強度をチェックしてくれるプラグインのセットアップをする?「y」

VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No: y

検証レベルを選ぶ。

There are three levels of password validation policy:

LOW    Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary                  file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2
  • LOW:8文字以上
  • MEDIUM:8文字以上 + 数字・アルファベットの大文字と小文字・特殊文字を含む
  • STRONG:8文字以上 + 数字・アルファベットの大文字と小文字・特殊文字を含む + 辞書ファイルでのチェック

本番環境ようなので、2を選択。
先ほど入力したパスワードの強度が合致していないと再度入力を求められます。
2度パスワードを打ち込むと、これで確定していいんだね?と言われるので「y」

Estimated strength of the password: 50 
Change the password for root ? ((Press y|Y for Yes, any other key for No) : y

New password: 

Re-enter new password: 
Estimated strength of the password: 100 
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y

匿名ユーザ( anonymous user )を削除する?「y」

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.

リモートから root ユーザでログインできないようにします。ログインを禁止する?「y」

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

デフォルトで作成されている test という名前のデータベースを削除する?「y」

Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.
 - Removing privileges on test database...
Success.

すぐに権限テーブルをリロードして変更を有効にする?「y」

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done! 

とりあえず、設定はできたかな?

もう一度動作確認

$mysql -u root -p
Enter password:(パスワード入力)

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.32 Homebrew

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

う、、動いた!!!泣

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)

中身も空になっていました!

一度mysqlからはexitして・・・
停止もして・・・

$ mysql.server stop
Shutting down MySQL
. SUCCESS! 

アプリに戻ってbundle install

同じエラーが・・・・・・・泣

下記記事を参考に進めました!
【Rails】MySQL2がbundle installできない時の対応方法

$ brew info openssl
openssl@1.1: stable 1.1.1h (bottled) [keg-only]
Cryptography and SSL/TLS Toolkit
https://openssl.org/
/usr/local/Cellar/openssl@1.1/1.1.1g (8,059 files, 18MB)
  Poured from bottle on 2020-05-21 at 18:53:48
/usr/local/Cellar/openssl@1.1/1.1.1h (8,067 files, 18.5MB)
  Poured from bottle on 2020-11-01 at 12:26:48
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openssl@1.1.rb
License: OpenSSL
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

and run
  /usr/local/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides LibreSSL.

If you need to have openssl@1.1 first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> /Users/mariko/.bash_profile

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"

For pkg-config to find openssl@1.1 you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"

==> Analytics
install: 835,013 (30 days), 1,906,254 (90 days), 7,237,126 (365 days)
install-on-request: 136,062 (30 days), 257,990 (90 days), 1,007,070 (365 days)
build-error: 0 (30 days)

この部分が重要らしい。

export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"

下記の二つのコマンドを実行

$ bundle config --local build.mysql2 "--with-cppflags=-I/usr/local/opt/openssl@1.1/include"
You are replacing the current local value of build.mysql2, which is currently nil

$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl@1.1/lib"
You are replacing the current local value of build.mysql2, which is currently "--with-cppflags=-I/usr/local/opt/openssl@1.1/include"

再度bundle install
インストールできました・・・・・!!!嬉泣

まとめ

アプリにMySQLを導入するまでかなり右往左往してしまいました。
読みづらかったらすみません。
少しでも誰かのお力に慣れたら嬉しいです。

参考にさせていただいた筆者の方々、本当にありがとうございました。

途中でSQLiteに変更する手順もあるみたいなので、今まで制作したアプリで試してみようと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 標準入力

はじめに

今回はプログラミング問題で標準入力を使うことが多いので、メモを残しておこうと思います。
使用言語はRubyで行います。

文字列の場合

1行1要素だけしか存在しない場合

標準入力
Tokyo
line = gets
p line
出力結果
"Tokyo"

1行に複数要素存在する場合

標準入力
Tokyo Osaka Kyoto
line = gets.split(' ')
p line
出力結果
["Tokyo", "Osaka", "Kyoto"]

splitメソッドを使用することで3つの要素をそれぞれ別のものとして配列に格納しています

複数行1つずつ要素が存在する場合

標準入力
Tokyo
Osaka
Kyoto
line = readlines
len = line.length
i = 0

while i < len
    line[i] = line[i].chomp
    i += 1
end

p line 
出力結果
["Tokyo", "Osaka", "Kyoto"]

上記のものの簡潔な書き方として、mapメソッドを使用したものがあります

標準入力
Tokyo
Osaka
Kyoto
line = readlines.map(&:chomp)
p line 
出力結果
["Tokyo", "Osaka", "Kyoto"]

複数行に複数要素が存在する場合

標準入力
Tokyo Osaka Kyoto
Japan USA China
line = readlines
len = line.length
i = 0

while i < len
    line[i] = line[i].chomp.split(' ')
    i += 1
end

p line
出力結果
[["Tokyo", "Osaka", "Kyoto"], ["Japan", "USA", "China"]]

上記のものの簡潔な書き方として以下のものもあります

標準入力
Tokyo Osaka Kyoto
Japan USA China
lines = []
while line = gets
    lines << line.chomp.split(' ')
end
p lines
出力結果
[["Tokyo", "Osaka", "Kyoto"], ["Japan", "USA", "China"]]

while line = getsとすることで、標準入力の値を全て取得するまで繰り返されます

標準入力
Tokyo Osaka Kyoto
Japan USA China
lines = readlines(chomp: true).map{|line| line.split(' ')}
p lines
出力結果
[["Tokyo", "Osaka", "Kyoto"], ["Japan", "USA", "China"]]

出力結果を見ると、受け取った値は文字列なので数値を受け取りたい場合は次のようにします

数値で受け取りたい場合

1行に1要素だけしか存在しない

標準入力
123
line = gets.to_i
p line
出力結果
123

1行に複数要素存在する場合

標準入力
1 2 3
line = gets.split(' ')
p line
出力結果
["1", "2", "3"]

このままだと文字列として扱われるので、mapを使用して数値型の配列に変換します

標準入力
1 2 3
line = gets.split(' ').map(&:to_i)
p line
出力結果
[1, 2, 3]

複数行に1つずつ要素が存在する場合

標準入力
1
2
3
line = readlines.map(&:to_i)
p line 
出力結果
[1, 2, 3]

複数行に複数要素が存在する場合

標準入力
1 2 3
4 5 6
lines = []
while line = gets
    lines << line.chomp.split(' ').map(&:to_i)
end
p lines
出力結果
[[1, 2, 3], [4, 5, 6]]

より簡潔に書く方法は下記

標準入力
1 2 3
4 5 6
lines = readlines(chomp: true).map{|line| line.split(' ').map(&:to_i)}
p lines
出力結果
[[1, 2, 3], [4, 5, 6]]

最後に

この他にもいろんな方法があると思うので随時更新していこうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】配列内の偶数or奇数のカウント方法

配列内にある値について、偶数もしくは奇数の数のカウントをするメソッドを作成します。

値が偶数の場合はeven?メソッドを使用し、奇数の場合はodd?メソッドを使用します。
※以下は偶数パターンのみ記載しています。evenをoddに変換することで奇数のカウントに使用できます。

使用例

Ruby
number = 2
number.even?

// →trueが返却される

解答例

Ruby
def count(number)
  count = 0
  number.each do |num|
    if num.even?
      count += 1
    end
  end
  puts count
end

解説

今回はメソッド作成のため、まず一行目にメソッド名と仮引数のnumberを記述しています。

Ruby
def count(number)

上述の通りeven?メソッドはtrueもしくはfalseのみ返却するため単体ではカウントできません。
そのため以下のように配列に対してeven?メソッドを使用するとエラーが発生します。

失敗例

Ruby
hairetsu = [1,2,6,8,10]
hairetsu.even?

// NoMethodError (undefined method `even?' for [1, 2, 6, 8, 10]:Array)

なお、二行目でcount = oと記載していますが、繰り返し処理の前に記載することでカウントの初期化をしています。

カウントするためにはeachメソッドによる繰り返し処理で行います。
流れとしてはtrueだった場合にはカウントアップし、falseの場合は何もせず次の要素の判定に進む、といったものです。

Ruby
number.each do |num|
  if num.even?
    count += 1
  end
end

最後にカウントしたものを出力するためにputsメソッドを使用しています。

Ruby
puts "count"

これで汎用的な配列内の偶数or奇数のカウントメソッドを作成することができました。
メソッドを呼び出す際はメソッド外から実引数に配列を指定してコールすることをお忘れなく。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ユーザー登録でなぜメールアドレスが必要か

大体の流れ

多くのwebサイトでは以下のような手順が取られている
1 : 新規登録画面でメールアドレスの入力を要求

2 : そのメールアドレスに対して本登録用のリンクを記載したメールを送信

3 : リンクから遷移した先のフォームに必要事項を記入

4 : 登録完了

なぜemailを使った認証が必要なのか?

不正登録を防ぐ

もし、メール受信なくユーザー登録が完了してしまった場合、無限にアカウントが作れてしまう。
その場合、不正に利用されてしまう可能性があるので手順を複雑化し、不正利用を防ぐのが狙い。

メールアドレスが有効か確認する

ユーザーとの連絡手段を確立するため。
もし、入力されたメールアドレスが間違っていた場合、ユーザーとの連絡が確立できず「ユーザー登録が完了した」事すらも伝えることができない。
よって、メールアドレスが正常に受信できるかどうか確認している

Railsでの認証

Railsでログイン認証をするにはdeviseというgemを使って実装するみたい。

[Rails] deviseの使い方(rails5版)

参考

参考にしたブログ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】DB保存時のカラムの制約(代表4つ)

この記事を書いた背景

データ保存時の制約の指定の仕方が、マイグレーションファイルとモデルファイルとそれぞれに書く方法があることを知ったので、改めて代表的なバリデーションをまとめてみました。(結構前に勉強したことですが、改めてqiitaにまとめていこうと思います。)

実施環境

macOS Catalina 10.15.7
VS Code 1.50.0
Ruby 2.6.5
Rails 6.0.0

①NOT NULL制約

→データが空の状態では保存ができない制約

【マイグレーションファイルへの書き方】
null: false

20200919092740_create_item.rb
t.string :address, null: false

【モデルファイルへの書き方】
presence: true

item.rb
validates :address, presence: true

②一意性制約

→重複して同じデータを保存できない制約

【マイグレーションファイルへの書き方】
unique: true

20200919092740_create_item.rb
t.string :address, unique: true

【モデルファイルへの書き方】
uniqueness: true

item.rb
validates :address, uniqueness: true

③主キー制約

→データが空の状態では保存ができない、かつ、重複して同じデータを保存できない制約
(NOT NULL制約かつ一意性制約)
(idカラムには自動で設定される制約)

【マイグレーションファイルへの書き方】
primary_key: true

20200919092740_create_item.rb
t.string :address, primary_key: true

※モデル名のID以外を主キーにわざわざ設定することは少ないと思うので、あまり使わないと思います。
※モデルファイルへの書き方は調べた限りどうやらなさそうです。

④外部キー制約

→外部キーとなるデータが必ず存在しないとデータ保存できない制約

【マイグレーションファイルへの書き方】
foreign_key: true

20200919092740_create_item.rb
t.string :address, foreign_key: true

※モデルファイルへの書き方は調べた限りどうやらなさそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

充電器を刺したらエラーが解決した話を頭の片隅に置いて欲しい

arienai.jpg

グリード「ありえないなんてことは、ありえない」 ーーー鋼の錬金術師

はじめに

正直しょーもない記事ですが、万が一でも誰かのためになればいいなと思いまとめました。

背景

メンターとしてプログラミングに関するエラー対応をしていた際に、以下のようなエラーに遭遇しました。

Rails5.2.4を使用し、RSpecの実行をしようとした際、cannot load such file -- spec_helper (LoadError)と詳しくは覚えていませんが、何かしらのNameErrorが同時に起こりました。

生徒さんが設定したファイル・フォルダ名やディレクトリの位置などが全て合っていることを確認し、当該アプリケーションを一度githubに上げて頂いたのち、私のPCでclone、テストを通してみました。

皮肉にも自分の環境では無事にテストが通りました。
どうしたこと、何か設定が違うのかと頭を悩ませていました。。。

解決へ・・・

その際、Zoomで会話をしていたのが生徒さんのPCの充電が残り1ケタで、自分の方がほぼフル充電であることに気づきました。
生徒さんは充電器を取りに行かれて、ご自身のPCに差し込んでもう一度テストを実行しました。

その結果、なんとエラー無くテストが実行されたのです・・・。

まさかーと思いましたが、私以外にももう一人同時にチェックしていた方がいらしたので、コーディングは間違いなく一切しておりません。

PCのパフォーマンスなど、そういった影響もあるのかな・・・?と思いました。
もし、何をどうやってもダメな場合、充電を十分にした上でプログラムを実行してみるのも最終手段として良いのかなと思いました。

似たような記事が見つからなかったので、一応残しました。
何か詳細が分かる方がいらしたら、是非コメントにお願いします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】TwitterAPI使用時に、httpで送られてくる画像のURIをhttpsに変換した方法

はじめに

yukiと申します。DMMWEBCAMP にお世話になって、今は WEB エンジニアとして勤務しつつ、自分で仲間を集めてサービス開発したり、プログラミングの家庭教師したり毎日エンジニアライフをエンジョイしています。

未経験から目指している方向けのサポートやエラー質問なども引き受けておりますので、気になった方は DM へお願いします。

前提と問題

RailsをAPIとして活用していて、gem twitterを使って画像収集をしていた際に問題が起こりました。
twitter APIが取得してくる画像のURIがhttpから始まっており、せっかくhttps通信ができているサイトに「安全ではありません」の警告が出てしまいました。

ちなみに、その時コンソールにはこんなエラーが出ていました。

Mixed Content: The page at 'https://hogehoge.com' was loaded over HTTPS, but requested an insecure image 'http://hogehoge.net/hoge.jpg. This content should also be served over HTTPS.

mixed contentとか言うらしいです。
最初は今回まとめる方法が思いつかず、フロントの方で何とかしていましたが、本来バックでやるべきなので修正しました。

対策

examples_controller.rb
  def show
    client = Authorization.init # 独自クラスです。クライアントの情報を入れています。
    @data = client.search("#収集したいハッシュタグ", result_type: "recent").take(4).collect do |tweet|
      {
        "image": "#{tweet.user.profile_image_url.to_s.sub('http', 'https')}",
        "name": "#{tweet.user.name}",
        "text": "#{tweet.full_text}",
        "tweet_link": "#{tweet.uri}"
      }
    end
    render json: {tweet: @data}
  end

何をしているか一応ご説明すると、特定のハッシュタグのついたツイートを4件収集し、jsonデータとして返しています。
今回重要なのは"image": "#{tweet.user.profile_image_url.to_s.sub('http', 'https')}",の部分です。

これは他のエンジニアの方に教えていただいたのですが、rails consoleでuser.profile_image_urlを見てみると、ちょっとよくわからないデータの形(?)で結果が返りますが、to_sすることで綺麗なURLになりました。

そこに、subメソッドを当てて変換している感じです。

注意としてはgsubではなくsubを使っていることです。
理由としては、万が一画像のURLの一部(先頭以外)に"http"と言う文字列があった場合に誤変換して、画像が表示されなくなってしまうからです。

誰かの参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【100点満点】プログラミングスクール卒業生向けにコーディングテストを考えてみた【Ruby】

はじめに

yukiと申します。DMMWEBCAMP にお世話になって、今は WEB エンジニアとして勤務しつつ、自分で仲間を集めてサービス開発したり、プログラミングの家庭教師したり毎日エンジニアライフをエンジョイしています。

未経験から目指している方向けのサポートやエラー質問なども引き受けておりますので、気になった方は DM へお願いします。

今回は、とあるところで「プログラミングスクールの卒業生に、コーディングテストをするとしたらどんなものを出すか?」という問を出されたので、当時(6ヶ月前位)の自分の回答を記したいと思います。

今ならソートを聞きたいなとか色々あるんですが、当時の思い出として共有します。
Rubyを学習して、ちょうど卒業した位の方は是非挑戦してみてください。自分も作った当時、同じ卒業生でした。

問題

100点満点採点です。

【問題文】
あなたはプログラミング勉強中の生徒で、日々沢山の勉強をしています。
今日は今月の初日と仮定します。
頑張り屋さんのあなたは、今月のプログラミングの勉強の仕方にルールを設けることにしました。
条件を厳守した上で、以下の問題に答えなさい。

【条件】
・90分以内にコードを書いて提出すること
・インターネットやこれまで学習したノートなどを見ないで解くこと
・問題文の通り、今日は*2020年の11月1日*と仮定して解き進めること
※この記事を読んだ月に合わせていただいて結構です。

・加点方式のため、わからない場合も出来る限りコードを書いてみること
※その際、分からなかった部分をコメントとして記入すること

【問題】
(1)今月の最終日を日付オブジェクトを利用して出力しなさい。
   ※但し、require 'date'と記載すると利用できるようになる。

(2)あなたは学習をする間、毎日問題を1問必ず解くことに決めました。
   また、日付に4がつく日は2問、素数の日は3問を解くことにしました。
   初日から学習を開始した場合、今月は合計何問の問題を解くことができるでしょう。
   ※但し、Primeクラスの利用は不可とする

(3)今月のカレンダーを次のような形式で出力してください。
https://drive.google.com/file/d/1_Km62H6c1WTzv1rWz4NfnwgVXDBC9r2c/view?usp=sharing

解答と解説と評価基準

answer.rb
# 100点中60点以上が合格

# (1)の解答例
require 'date'
year = Date.today.year
month = Date.today.mon
lastday = Date.new(year, month , -1).day 
puts "(1)答え:"+"#{lastday}"

=begin
    (1)評価規準 満点【10点】
      ※yearとmonthが求められず、最終日を 2020 5 と直接入力していても減点しない
      ※但し、同点の候補者がいた場合.yearや.monなど再利用性のあるコードを書いている者を評価する
    1.Date.newができている【5点】
    2.答えが28,29,30,31のいずれかで、今月の最終日と対応している【5点】
=end

# (2)の解答例
# 解いた問題の個数の初期化をしています。
count = 0

# 素数判定のメソッドです。#1で呼び出します。
def prime?(num)
  return false if num == 1 
  (2..num).each do |i|
    if num % i == 0 && num == i
      return true
    elsif num % i == 0
      return false
    end
  end
end

# 初日から最終日まで繰り返し処理を行います。
(1..lastday).to_a.each do |date|
    # 日にちに4という数字が含まれていた場合の処理です。
  if date.to_s.split("").include?("4")
    count += 2
    #1 日にちが素数だった場合の処理です。
  elsif prime?(date)
    count += 3
  else
    count += 1
  end
end
puts "(2)答え:"+"#{count}"

=begin
(2)評価規準 満点【30点】
    1.素数の判定コードが書けている【10点】
      ※素数を全て書き出している場合は【5点】
    2.4のつく日を判定するコードが書けている(全て書き出しも可)【5点】
    3.繰り返しを使って毎日、1問を解くコードが書けている【5点】
    4.加点をさせる変数の初期化や加算ができている【5点】
    5.解答があっている【5点】
=end

# (3)の問題について
puts "(3)答え:\n" 
week = ["Su","Mo","Tu","We","Th","Fr","Sa"]
puts week.join(" ") 

# 各月の初日の曜日を数値化させています。
day = Date.new(year,month,1).wday
# 曜日 + 1桁の日にちの半角スペース分 = 3半角スペース分を乗算して初週の右寄せをしています。
print "   " * day

(1..lastday).each do |date|
  print date.to_s.rjust(2) + " "
  day += 1
  if day % 7 == 0
    puts "\n"
  end
end

if day % 7 != 0
  print "\n"
end

=begin
(3)評価規準 満点【50点】
    1.一行目の曜日の出力ができている 【10点】
    2.日にちの出力ができている【5点】
    3.工夫して各日の間に半角スペースを入れて出力ができている【5点】
      ※"1 ","2 "のように手入力している場合は【5点】
    4.7日区切りにできている【10点】
      ※繰り返しや改行を使わずに、putsを多用している場合は【5点】
    5.1桁の日にちを出力する場合、先頭にスペースを入れることができている【5点】
    6.第1週を右寄せにできている【5点】
    7.最終週を左寄せにできている【5点】
    8.解答が合っている【5点】
=end

=begin
(その他)満点【10点】
    解答コードの見やすさ、読む人への配慮、処理の方法、導き出そうとした過程などの観点から
    評価理由とともに、採点者が最大10点まで加点をしてください。
=end

まとめ

懐かしいなぁと思いました。何でこのような問題にしたか、想いみたいなのも当然あったのですが、だいぶ経ったので忘れてしまいました。
コーディングテストのいい悪いはともかく、当時を振り返りつつ、今ならどんなテストを作るか考えてみたいです。

解けたら是非ご連絡ください( ◞´•௰•`)◞

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【文系未経験エンジニア志望の方向け】逃げてきた数学にProject_Eulerを通じて向き合いませんか?

はじめに

yukiと申します。DMMWEBCAMP にお世話になって、今は WEB エンジニアとして勤務しつつ、自分で仲間を集めてサービス開発したり、プログラミングの家庭教師したり毎日エンジニアライフをエンジョイしています。

未経験から目指している方向けのサポートやエラー質問なども引き受けておりますので、気になった方は DM へお願いします。

私はかつてド文系で国語科の高等学校の教員をやっていたのですが、色々あって今は上のキャリアで楽しく過ごしています。
大学受験の際に数学は2Bまで学習していたのですが、プログラミングをする時にとても役立ちました。

もし、高校の頃に 「ちょっと数学を避けてしまったな…。でも考え方がプログラミングに使えそうだしな…。」と言う方向けに、今回は数学とプログラミングが同時に学習・復習できるProject Eulerをご紹介します。

Project Eulerとは

プロジェクトオイラーと読みます。
https://projecteuler.net/

説明はwikiより引用。

プロジェクト・オイラー(英: Project Euler、名称はレオンハルト・オイラー由来)は、数学やプログラミングなどに興味を持つ大人や学生が主な利用者であり、プログラミング (コンピュータ)による一連の計算問題の解決を目的としたウェブサイトである。 400以上[2]の問題の他に毎週末毎に1問ずつ増えており、様々な難問が用意されているが、 一般的なスペックのパソコンで効率的なアルゴリズムを用いれば、いずれも1分未満で解ける。

自分はプログラミングスクールでの学習が終わったのち、数学の復讐もしたいと思い、こちらに取り組んでいました。
rubyで解いたリポジトリはこちらです。(50位までやりました。)

数学チックな問題、かつ出力の方法も難しいような問題がたくさんあり、非常に頭を使いました。

例題

では、試しに1問目をみてみましょう。
と、その前に、日本語のサイトが前はあったのですが落ちています・・・。

と言うことで、元サイトを翻訳してくれる素晴らしい拡張機能を先に入れましょう。
https://chrome.google.com/webstore/detail/project-euler-translate-i/oeicjfkbfahmdklgoollemcahaljgklo?hl=ja

10未満の自然数のうち, 3 もしくは 5 の倍数になっているものは 3, 5, 6, 9 の4つがあり, これらの合計は 23 になる.
同じようにして, 1000 未満の 3 か 5 の倍数になっている数字の合計を求めよ.

自然数って何だっけ…?って思った方、大丈夫です。ぐぐりましょう。

私の解答

answer.rb
max_number = 1000
answer = 0

for num in 1..max_number -1
  if num % 3 == 0 || num % 5 == 0
    answer = answer + num
  end
end

puts answer

過去に作った解答なので、もっと良い方法があるかもしれません。

オススメする理由

文系からエンジニアに転職する方も多い昨今、数学を振り返ることはとても重要だと考えています。私は2Bまでしか履修していないので言えた口ではないのですが、数学自体は嫌いではなかったので 「問題を細分化し、ロジックを組んで答えにたどり着く」 と言う論理的な思考は非常にプログラミングに生きているなと感じます。

ただ、教科書を引っ張り出して1からやり直すのも大変ですし、せっかくならプログラミングを勉強しながらやるのも良いんじゃないかなと思ったので紹介しました。

私はProject Eulerをやってみて、嫌いではなかった数学がちょっと好きになりました。なぜなら、「プログラムが」計算をしてくれるからです。これまでは面倒くさい公式を使って、計算ミスに気をつけながら、ノートを汚くして解いていた数学が、ロジックさえあっていれば答えが綺麗に出てくれるので、とても快感でした。

もしかしたら、数学嫌いの克服にもなるかもしれないので、是非一度挑戦してみてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む