Ruby on Rails チュートリアル x日目(1章~9章)
久しぶりの投稿になります。
今日で、railsチュートリアルを9章まで終えることができました。
実は、一度10章までやったのですが、段々とわからないことが多くなり、遂には現実逃避の読書に浸ってしまう次第に。(おかげで3冊も400ページくらいの本を読みましたが。)
しかし、これはまずいなと感じ、コンピュータの歴史を調べたりして無理やりモチベーションを上げて、もう一度じっくり復習する時間を取り、RubyやCSS、Gitの勉強をやってから1~9章の2週目を行いました。
9章を終えたのですが、ここで疑問が。
疑問①
『次に統合テストでも同様のヘルパーを実装していきます。ただし統合テストではsessionを直接取り扱うことができないので、代わりにSessionsリソースに対してpostを送信することで代用します (リスト 8.23)。メソッド名は単体テストと同じ、log_in_asメソッドとします。』とあるが、なぜsessionを直接取り扱うことができないのか。
疑問②
『また、リスト 9.24で定義したlog_in_asヘルパーメソッドでは、session[:user_id]と定義してしまっています。このままでは、current_userメソッドが抱えている複雑な分岐処理を統合テストでチェックすることが非常に困難です。ただありがたいことに、Sessionsヘルパーのテストでcurrent_userを直接テストすれば、この制約を突破することができます。』
とあるが、なぜか?
の二つです。
まず最初に…
“9.3.1 [Remember me] ボックスをテストする“で何をやっているのかを少しまとめます。
Railsチュートリアルに書いてある通りなのですが、ユーザが記憶されるにはログインが必要です。リスト 8.23ではpostメソッドと有効なsessionハッシュを使ってログインしています。
リスト 8.23: 有効な情報を使ってユーザーログインをテストする
test/integration/users_login_test.rb
require 'test_helper' class UsersLoginTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) end . . . test "login with valid information" do get login_path post login_path, params: { session: { email: @user.email, password: 'password' } } assert_redirected_to @user follow_redirect! assert_template 'users/show' assert_select "a[href=?]", login_path, count: 0 assert_select "a[href=?]", logout_path assert_select "a[href=?]", user_path(@user) end end
だけど毎回書くのは面倒、使いまわせるようにlog_in_asなるヘルパーメソッドをいっちょ作りましょう。ということで以下
『ログイン済みのユーザーをテストする方法はいくつかありますが、今回はコントローラの単体テストを使っていきましょう。具体的には、sessionメソッドを直接操作して、:user_idキーにuser.idの値を代入してみます (これはリスト 8.14の方法と同じです)。』
とあります!
思い出すんだ…リスト 8.14…。
『同じログイン手法を様々な場所で使い回せるようにするために、Sessionsヘルパーにlog_inという名前のメソッドを定義することにします (リスト 8.14)。』
リスト 8.14: log_inメソッド
app/helpers/sessions_helper.rb
module SessionsHelper # 渡されたユーザーでログインする def log_in(user) session[:user_id] = user.id end end
確かこれでユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成されるんですよね。
もどりまして
リスト 9.24: log_in_asヘルパーを追加する
test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test' . . . class ActiveSupport::TestCase fixtures :all # テストユーザーがログイン中の場合にtrueを返す def is_logged_in? !session[:user_id].nil? end # テストユーザーとしてログインする def log_in_as(user) session[:user_id] = user.id end end class ActionDispatch::IntegrationTest # テストユーザーとしてログインする def log_in_as(user, password: 'password', remember_me: '1') post login_path, params: { session: { email: user.email, password: password, remember_me: remember_me } } end end
特徴①メソッド名の違い
前回のlog_inメソッド(8章)はテストじゃなく、ログインのためのメソッド、今回は[Remember me] ボックスをテストする用のなのでlog_in_asメソッド
と区別しているので名前が違います!
特徴②同じtest/test_helper.rbファイルにまとめている!(classが二つ)
これはまあ、上はおまけらしいですが(現時点で)、重要なのは我々人間側からみて同じ名前であるということ。
ログイン済のテストのときは脳死でlog_in_asとソースに記述して呼び出せばいいんだよ。のことらしいです。
名前が同じでも、クラスが違うから適材適所に呼び出されるって感じなのかな。
で、ここからが本題。
疑問だったことは(再掲)
疑問①
『次に統合テストでも同様のヘルパーを実装していきます。ただし統合テストではsessionを直接取り扱うことができないので、代わりにSessionsリソースに対してpostを送信することで代用します (リスト 8.23)。メソッド名は単体テストと同じ、log_in_asメソッドとします。』とあるが、なぜsessionを直接取り扱うことができないのか。
疑問②『また、リスト 9.24で定義したlog_in_asヘルパーメソッドでは、session[:user_id]と定義してしまっています。このままでは、current_userメソッドが抱えている複雑な分岐処理を統合テストでチェックすることが非常に困難です。ただありがたいことに、Sessionsヘルパーのテストでcurrent_userを直接テストすれば、この制約を突破することができます。』
とあるが、なぜか?
です。
順番にみていきます。
まず①では2つのlog_in_asについてみます。
class ActiveSupport::TestCase は単体テストです。
class ActionDispatch::IntegrationTest は統合テストです。(Integration:統合)
単体テストではsessionメソッドを直接操作しています。これはオッケーです。
しかし下の方は、統合テストなのでメソッドは直接操作できません。なぜなのか。
答えはrailsの創造主様がそう作ったからだそうです。創造主であるデイヴィッド・ハイネマイヤー・ハンソン曰く『セッションは、コントローラの内部構造です。統合テストは、コントローラテストよりもブラックボックスです。このようにコントローラの内部をテストする必要はないと思います。代わりに、UIに表示されるものをテストするようにテストを作り直します。』と仰っています。
なるほど。よくわからんw. ⇒(https://github.com/rails/rails/issues/23386)
そして②の疑問ですが、
そもそもテストしたい箇所はsession[:user_id]がnilのときです!勝手に定義されてしまっていてはテストができない!ということ。
だからsessionヘルパーのテストで直接テストしているということになります。
(このときの@user=users(:michael)はfixtureのテストデータを用いている)
感想
9章めっちゃ難しかったです。正直、6割くらいしか理解できていないと思います。また挫折しそうですが、上記の疑問をいつか解決して記事で発信できるように頑張りたいと思います。(笑)
Ruby on Rails チュートリアル 12日目(5章)
- はじめに!
- アセットパイプライン
- Missing :controller key on routes definition, please check your routes.の対処法
- undoの演習
- jquery-railsを導入
- まとめ
はじめに!
Ruby on Rails チュートリアルの5章が終わりました!
5章では、フロントエンド寄りであるレイアウトを作り、見た目を綺麗にしたり、urlから画面遷移する機能を作ることを主におこないました。
本題に入る前に少し無駄話。
WSL2 ってご存知でしょうか?
現在、私はチュートリアルをLinux環境で実行しておりますが、これはWindowsのvirtual boxという仮想化ソフトを使って仮想OS上で動かしています。
初めは、すぐにmacbook proの13インチを購入しようと思っていました。
理由はmacbookがOS Xと呼ばれるUnixベースのOSを採用しており、Unixが使えるからです。(あとスタバで…)
しかし、バタフライキーボード廃止の新型が出るかもと噂を聞き、買うのを渋っておりました。それにやっぱ高い
しかし、つい最近にwsl2と呼ばれるWindows内で完全なLinuxを実行できる仕組みが近々一般リリースされるというニュース記事をみました。(しかもwsl2はdocker対応)詳しい仕組みは割愛しますが、
独自のLinuxカーネルがプログラム中に含まれており、専用のVM(仮想マシン)ユーティリティのなかでこれを実行することで、完全なLinux対応を果たしているそうで
これによって仮想OSを立てるより高速に作業ができるんだとか…もしかしてmacいらない?
一般提供されたら使ってみようと思います!
皆さんも興味がありましたら是非調べてみてください。
アセットパイプライン
アセットパイプラインについてが、いまひとつ理解できなかったので以下のサイトを参考にさせていただきました。
www.transnet.ne.jp
「人に分かり易く」かつ「機械にも分かり易く」という目的でRailsはどんどん進化しているということなのですね。
Missing :controller key on routes definition, please check your routes.の対処法
rails t(テスト)を実行したら、いつものRed画面ではなく、謎の結果が…
Missing :controller key on routes definition, please check your routes.
どうやらテストのエラーではなく、コンパイルエラー?に引っかかって怒られたみたいです。
以下のQiitaの記事からヒントをもらい、
qiita.com
Rails.application.routes.draw do root 'static_pages#home' get '/help', to: 'static_pages#help' get '/about', to: 'static_pages#about' get '/contact', to: 'static_pages#contact' end
のところを
Rails.application.routes.draw do root 'static_pages#home' get '/help', to: 'static_pages#help' get '/about', to: 'static_pages#about' get '/contact', to: 'static_pages/contact' ←#ではなく、/にしていた。 end
ことが原因と判明しました。
(おまけ)
..., to:'static_pages#help' , as : 'helf' でもエラーが発生
正しくは
..., to:'static_pages#help' , as: 'helf'
勝手にスペースを入れたのが間違い
vimでも変色しなっかったことに気が付くべきでした。スペース混入のエラーは見つけにくいですね。
ちなみにリスト 5.28のテスト作成後時点に $ rails routes で確認すると
Prefix Verb URI Pattern Controller#Action root GET / static_pages#home helf GET /help(.:format) static_pages#help about GET /about(.:format) static_pages#about contact GET /contact(.:format) static_pages#contact
となります。
undoの演習
チュートリアルでなぜか急にundoの演習です。
vimではescを押してノーマルモードにし、
:uで 元に戻す(undo)
ctrl + r (=:^r) やり直し(redo)
操作をおこないます。
jquery-railsを導入
これはチュートリアルには無い内容になります。
チュートリアルの一環でブラウザを使った結果を表示させる際に、ブラウザの大きさ自体を変えると以下の画像のような現象が起こります。
これだと少し見にくくなりますね。
jquery-railsを導入することで改善されるようなので試してみました。
まず、
gem 'jquery-rails' , '4.3.1'
をGemfileに追加して
$ bundle install
を実行します。
続いてapp/assets/javascripts/application.jsのファイルに
//= require jquery
と
//= require bootstrap
を追記します。
あとはヘッダー(app/views/layouts/_header.html.erb)の修正をおこないます。
<header class="navbar navbar-fixed-top navbar-inverse"> <div class="container"> <!-- 追記ここから--> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <!-- 追記ここまで--> <%= link_to "sample app", root_path, id: "logo" %> <!-- 追記ここから--> </div> <!-- 追記ここまで--> <nav> <!-- ulタグ内に「id="navbar"」を追記、classに「navbar-collapse collapse」を追記 --> <ul id="navbar" class="nav navbar-nav navbar-right navbar-collapse collapse"> <li><%= link_to "Home", root_path %></li> <li><%= link_to "Help", help_path %></li> <li><%= link_to "Log in", '#' %></li> </ul> </nav> </div> </header>
Ruby on Rails チュートリアル 11日目(4章)
はじめに!
Ruby on Rails チュートリアルの4章が終わりました!
ところで!この間ツイッターを見ていたら、モダンweb系開発企業を就活で受けたという方が質問内容を投稿しているのを拝読しました。
前章で学んだGETとPOSTの違いって結構聞かれるのですね。他にもこれから学ぶログイン機能の実装方法なども聞かれるそうで…怖いですね。
復習も定期的にやらないと、
それと本を買いました!www.amazon.co.jp
買って使ってみたところ、正直、参考書の購入は不要不急ではないと思いました。理由としましては、もともとJavaを触っていてRubyの記法を学ぶのにRailsだけで十分だと感じたことと、何より
情報量が多い。
いや、いいことなんですけど、周回するようなものではないですね。辞書用かな。初心者向けでもないですね。(そもそもプロを目指す向けって書いてあるだろ!と怒られそう)
いずれ買うことになると思ってましたし…、深くrubyの仕組みを理解する分にはとても満足できそうです。(星5)
さて、本題に入ります!!
今日も感想や、気づきを備忘録形式で載せていきます!
①ページタイトルとは
恥ずかしながら、ページタイトルという用語を誤解していました。
てっきりwebページの標題のことかと思いきや、ページタイトルはブラウザの上にでてくるタブに表示されるのですね。
なので、チュートリアルを読んでいて『あれ?変わんない』と暫く悩んでいました。(笑)
②irbとrails console
私はrailsのコンソールではなく、irbコマンドでrubyの対話型プログラミングをおこないました。
ですが、しばらく進めると、まるで私の行動を読み取ったかのように前触れもなく『irbではできないヨ』と注意書きが!
Ruby on RailsはRubyのフレームワークですが、書き方には少し異なる点もあるみたいですね。
③4.2.4の演習
putにしなかったので問3でfalseが出てしまいました。
>> def palindrome_tester(s) >> if FILL_IN >> puts "It's a palindrome!" >> else >> puts "It's not a palindrome." >> end >> end
④クラス内におけるメゾッドの順番
4.4.5 の演習1についてです。
先に何にはまったかと言うと、以下のようなエラーが起きました。
>> example.email="user@example.com" => "user@example.com" >> example.formatted_email => " <user@example.com>" ➡氏名が表示されない!! >> example.full_name => "Example User" ➡氏名が格納されている!動作はしているみたい!
ちなみにソースコードは以下の通りです。
class User attr_accessor :first_name, :last_name, :email def initialize(attributes = {}) @first_name = attributes[:first_name] @last_name = attributes[:last_name] @email = attributes[:email] end def full_name @full_name = "#{@first_name} #{@last_name}" end def formatted_email "#{@full_name} <#{@email}>" end end
結論を先に言いますと、full_nameメソッドとformatted_emailメソッドの上下を入れ替えたら正常に動きました。
どういう試行錯誤をしたかというと、
最初の実行結果では、full.nameメゾッドはしっかり値が格納され、表示されている
↓
first、lastは直接シェルでぶち込んでいるから保存されているだけのかな?
↓
ということは、full.name動かしている時点ではそこだけがうごいて、保存されている値が格納されるけど、formatted_emailでは、full_nameは別の宣言されたメゾットで値を格納しているがゆえに呼び出せていないのではないか?
↓
よくわからないけど、逆にしよう。
こんな感じです(笑)
class User attr_accessor :first_name,:last_name, :email def initialize(attributes = {}) @first_name = attributes[:first_name] @last_name = attributes[:last_name] @email = attributes[:email] end def formatted_email "#{@full_name} <#{@email}>" end def full_name @full_name = "#{@first_name} #{@last_name}" end end
すると、できました。
そういえば前にpython を使ってロボット開発の勉強していた際にもこんなことがあった気がします。
つまりは、後者のソースコードならformatted_emailを呼び出した後にfull_nameが実行され、値が格納されてからformatted_emailが実行される
または、ソースコードの後ろから実行されていく可能性があるみたい。
まとめ
うーん
最後のメソッドの順番は難しかったですね。オブジェクト指向もちょっと怪しかったですし、4章でこけてて大丈夫なのか?と不安になりました。
次は5章です!
まあ、完璧主義はwebエンジニアにはあまり向かないと云いますし、とりあえず先に進もうと思います!
もちろん復習もしっかりしますが…(笑)
Ruby on Rails チュートリアル 7日目(2章, 3章)
Ruby on Rails チュートリアル2章!
久しぶりの投稿になります。
先週はいろいろあって、チュートリアルをなかなか進めることが出来ませんでした(言い訳ですが(笑))。目標は4章だったのですが、結局3章までのコンプになります。
まず2章のエラーについてです。
データモデルについて実験をしていた時です。rails consoleを順次実行したのですが、なぜか以下のエラーが...
irb(main):001:0> first_user=User.first User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 2, name: "Okarin", email: "Okabe@example.com", created_at: "2020-03-09 12:05:57", updated_at: "2020-03-09 12:05:57"> irb(main):002:0> first_user.microposts Micropost Load (0.4ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? LIMIT ? [["user_id", 2], ["LIMIT", 11]] => #<ActiveRecord::Associations::CollectionProxy []> irb(main):003:0> micropost = first_user.microposts.first Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."id" ASC LIMIT ? [["user_id", 2], ["LIMIT", 1]] => nil irb(main):004:0> micropost.user Traceback (most recent call last): 1: from (irb):4 NoMethodError (undefined method `user' for nil:NilClass) irb(main):005:0> exit
うーん、わからないけどデータベースのアクセスに不具合がありそう。
よくよく見ると1人目のユーザーIDが?になっている。そういえばユーザーを追加したり削除するときに、1人目のUserを削除した気がする、、、
ということでデータベースを初期化!
もういちど登録することで解決しました。良かった。
最初のUserを削除してしまったせいでしたね。もしかしたらデータベースを初期化せずとも更新すれば良かったのかもしれません。
Ruby on Rails チュートリアル3章!
bitbranchでプッシュする際に、間違いのoriginを作成してしまいました!(git remote add originの際に名付けをミス)間違えたローカル上のorogin(リモート追跡ブランチ)を削除することができず、いろいろと試したのですが、結局アプリを作り直しました。(笑)
いやもう、リポジトリ作成とpushは次からは慎重にやります...(戒め)
テスト駆動開発(TDD)
しかしテストを先に作ってからプログラムを構築していくという手法は、C言語やJavaを扱っていた私からすると、とても新鮮でしたね。まだこの手法の真の恩恵を受けるに至ってはいないと思いますが、確かに。テストコードを書く手間とバグを取り除く手間を天秤にかけたらテストコードを先に記述する方が効率が良い、というのはとても理に適っていると思います。現に、チュートリアルでは何度もRedを連発しましたが、テストコードを追えば簡単にエラーの場所を発見することが出来ました。リグレッションテストができるという点も大きなメリットですね。C言語は回帰バグでエンドレスにシステムが動いたりしますから…。
Ruby on Rails チュートリアル 1日目(1章)
環境の構築
本日は、Ruby on Rails チュートリアルの中でも最初の環境構築設定をしました。チュートリアルの中ではAWSのCloud9を推奨していましたが、頑張ってLinux環境(Ubuntu)での構築を試みます。本当はmacのunix環境が良かったのでずが... もうすぐ新型mac book proが出ることを信じて待ちます!お願いappleさん!
最初は順調だったのですが、bundle install でいきなりエラーが!
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
An error occurred while installing sqlite3 (1.3.13), and Bundler cannot continue.
Make sure that `gem install sqlite3 -v '1.3.13' --source 'https://rubygems.org/'` succeeds before bundling.
ファ?
洗礼でしょうか?(笑)
ググったのですが、解決せず。
現場(エラーコード)を観察するのは基本だと云われたことを思い出し、エラーをもう一度じっくり見ます。
sqlite3.h is missing. Try 'brew install sqlite3', 'yum install sqlite-devel' or 'apt-get install libsqlite3-dev' and check your shared library search path (the location where your sqlite3 shared library is located).
あ、
書いてあった…(笑)
brew install sqlite3 と sudo apt-get install libsqlite3-dev' (管理者コマンドつける)を実行すると
上手くいきました。良かった
AWS Cloud9
先程、解決した環境構築エラーですが、一時、エラー解決が面倒になってAWSのCloud9でIDEを入れていました。クレジットカードの登録に多少ビビりましたが、これがめっちゃ便利!環境が既に整備されているので、バージョンの調整とかとは無縁!これから先に発生する未解決エラーに備えて同時進行していこうと思います。また、そのうちにAWSを使ったサービス構築も視野に入れているので、そのときにCloud9以外のサービスも勉強するつもりです。
Git入門!
とりあえずRuby on Rails チュートリアルはweb表示まで修了したので、続いてはGitでのソース管理です!といっても大学では情報工学に在籍しているにも関わらず、恥ずかしながらgitを使ったことがありません。あとでやろうと先延ばしにしてきたつけですかね。gitは本格的にやりたかったので、チュートリアルはちょっと休んでgitについて勉強します。教材はこれ!
Amazon : https://www.amazon.co.jp/dp/B071D4D6XX/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1
とりあえず表紙買いしました(笑)
結構評判も良いし、中身も初心者向けで、分かり易い図解と量だったので購入しました。
ざっくり学んだ重要用語は
ですね。
個人的にはこの参考書が良書の為か、表式の変わったSourceTreeの操作法以外はすんなりと進みました。
あとGithub Pages というドメインやサーバーの手続きがいらないwebページ公開ができるそうで、ポートフォリオに使えそうかな?
次回は再びチュートリアルに戻り、実際にgitを使ったリポジトリの作成とその管理、そしてHerokuについてやりたいと思います!
github : https://github.com/NAiZ123
twitter : @NAiZ302
Qiita : https://qiita.com/NAiZ
ブログはじめます!
ブログを閲覧して頂いた方、誠にありがとうございます!
皆さん、初めまして。NAiZと申します。今日からブログを始める駆け出しエンジニアです!
自己紹介!
まず初めに、私が誰なのかということで、自己紹介させていただきます。私は現在、情報工学を学んでいる大学3年生です。千葉県に住んでいます。趣味はキャンプ、写真撮影、陶芸です。(陶芸はN〇Kの連続テレビドラマ小説に触発されて初めました。)あと落書き程度の小説創作もしています。好きなアニメは「ハクメイとミコチ」です。
大学では画像認識自律走行ロボットをArduinoとRaspberry Pi3(open cv) で開発したり、プログラミングスクールのアルバイトをしていました。
将来の目標はアメリカでフルスタックエンジニア になることです。去年までは、SIerでSEになろーかなと、漠然に考えていたのですが、就職活動中の自己分析で新しいテクノロジーやものづくりに興味があるならWEB系エンジニアがいいじゃん!と思い立って、また、ブロックチェーンに魅了されて上記の目標を掲げました。
現在は就職活動を終了し、奨学金を借りて大学院へ進学を決意。ベンチャー企業へインターンシップ学生として参加させて頂きながら、その間に英語とweb系プログラミング言語を猛勉強するつもりです。
やりたいこと!
私が、これから何をやっていきたいかを綴ります。まず、web言語はRuby on Railsとgitの勉強です。youtubeのインフルエンサーが発信されている内容を参考にして、web業界を目指すならRuby on Railsをやったほうが無難かなと感じ、C言語とJava言語については大学でかなり触れているので、とりあえずはRailsチュートリアルから始めたいと思っています。
あと英語については、まずはtoeicですかね。toeic勉強しても喋る力はつかないよーと仰る方も世間では多いですが、まあ、まずはtoeic600点を目指してみようかなと思います。あ、私は英語が大の苦手でtoeic400点台です。(笑)
後々はイーサリアムの勉強と、AWSを使った個人サービスの開発。さらに情報セキュリティ領域、ロボット開発(ROS等)についても触れていきたいです。
まとめ!
まとめますと、
githubも始めましたので下にURLを貼っておきますね。そのうちはQiitaの記事も書けるようになりたいですね。
それでは頑張っていきたいと思います!
github : https://github.com/NAiZ123
twitter : @NAiZ302
Qiita : https://qiita.com/NAiZ