Railsチュートリアル一周目
Railsチュートリアルを進めていくときにつまづいたところ、勉強になった所をまとめていきます。
#第1章
環境構築
最新のRuby on Railsチュートリアルでは、AWS(アマゾンウェブサービス)のCloud9というブラウザで動作する開発環境を利用します。
よって、使用するパソコンに依らずにチュートリアルを進めることが出来る。
前提知識としてCUI(コマンドプロントとか文字でパソコン操作するやつ)とかは必要だと思う。Progate一通りやっていれば乗り越えれるはず!
つまづいたところ
のちのちになるのだが、Cloud9がハマる要因を作り出してくれたのでメモ:
Cloud9を開いたまま一定時間経過すると、Terminalのカレントディレクトリが勝手にホームディレクトリに移る。
これで何が起こるかというと、チュートリアルでcdしてhello_appに移動。ちょっとトイレいってご飯食べている間にcdがホームに移動。チュートリアルの説明ではカレントディレクトリは省かれているので気づかずに進める。git initしてなかったっけ?git initしてん!?なんでこのファイルコミットされとるんじゃ?は!?え!?Gitわからん!→勉強。んー?やらなんやらしておかしくなって気づいたら1時間。。。
##利用したサービス
・Git
・GitHub
・Heroku
###困ったところ
やっばりGitでつまづく。Gitの公式リファレンス日本語版をじっくり読んでなんとなくGitが使えるようになった?はず。
#第2章
RailsのscaffoldジェネレーターでサクッとWEBアプリを作成しました。
WEBってこうやって動いてんのね、少なくともRailsはMVC(Model-View-Controller)で成り立ってんのか。ということがわかりました。
##アプリケーションの設計
アプリを作るときには設計を考えます。そのときに利用できる理論、ここではREST理論などを勉強しました。RESTはWebサービスの設計モデルで、RESTなサービスはURIにHTTPメソッドでアクセスすることでデータの送受信を行っています。
RESTで利用されるHTTPメソッドは、CRUD操作と対応している。例えば、HTTPのPOSTは、CRUDのCREATEと。GETならREADみたいな感じ。
##MVCの挙動
RailsのMVCを図式を通して理解した。演習課題ではブラウザに/users/1/editというURLを入力した際のMVCを図示した。図の作成にはdraw.io( https://www.draw.io/ )を利用した。
##データモデル同士の関連付け
Progateでは関連するデータ同士をidで紐づけするために、find_by関数もしくはWhereを利用していた。例えば、Userのidが1で、Postのuser_idが1のデータを1件取り出すために/post/1/showというURLにアクセスした場合には、Post.find_by(user_id: params[:user_id])とかしていた。(例えがながい。。。)
一人のユーザーには複数の投稿がデータとしてあるとき、こんな記述でいいらしい。
has_many :microposts。書くところはUserモデルのとこ。
もういっこ、一つのポストは一人のユーザーにのみ属しているときには、
belong_to :user。書くところはPostモデル。
これだけで異なるデータテーブルが紐づけされちゃう、すごーい。
##本番環境へのデプロイ
Railsチュートリアルでは本番環境をHerokuとしている。今まで本番環境ってなんぞ?なにが違うのさと思いながら過ごしていた。それが次のコマンドで本番環境というものを知ることができた。
heroku run rails db:migrate。railsで定義したモデルで本番環境のデータベースを更新する命令です。あ、そっか。本番環境にもデータベースがあってそっちでもマイグレーションするよね。となったらなんかちょっと本番環境を掴むことが出来たんです。
#第3章
Sample_appというアプリの作成を通じて
- 新しいcontrollerを
rails g controller コントローラー名 アクション名
で追加した。 - ルーティングはconfig/routes.rbでおこなった。
- テストの意義、やり方を学んで実践した。
- Railsビューでは、ERB(埋め込みRuby)を使ってページを構築した。
<% %>
←これ - Railsのレイアウトでは、ページの共通部分をテンプレートに置くことでコードの重複をなくした。
##失敗を挽回する
railsのgenerate controller hogeで生成したコードを取り消したいときは
$ rails destroy controller hoge
で消えてくれる。generateで生成したコードは複数のファイルに跨っているので手動で修正するのはあぶない。やらかしたら思い出せるようにしておこう。
他にもマイグレーションを戻すなら
$ rails db:rollback
失敗を正確に戻すのは大切。袋小路に突っ込んだときにも思い出そう。
##Git新発見
恒例のGitつまづき。今回はこんな感じ
- Unixのmvコマンドでファイルを移動していた。そしてブランチを何故か切った。
- ふと、Gitってファイルの移動も記録してくれてんだろうか、と気になり前のブランチへcheckout。
- Gitからエラー「ファイルがこんなとこにあんだけどわい知らへんで、消すか移動しといてや」
調べた。どうやらGitにファイルの移動や削除を認識させるためにはrm や mv
ではなくgit rm とか git mv
を使うらしい。
#第4章
Ruby風味のRailsと題して、Rubyの基礎知識を拡充する章でした。もちろんRailsの仕組みに直結しているので一粒で二度美味しい。
##Rubyの特徴的な仕様
・関数呼び出しに()がいらない。
・ハッシュ。 { キー => 値, キー => 値 }。これは連想配列に似てるね
・シンボル。:を先頭につけた単語がシンボル。読み込み早いらしい。
・ハッシュとシンボルの合わせ技
{name: "Uki", age: 28}
これは以下と同値
{:name => "Uki", :age => 28}
キーには文字列、数値もつかえるよ
{"name" => "Uki", "age" => 28, 1 => "one"}
##Railsビューには膨大な組み込み関数。そしてカスタムヘルパー
app/helpers/application_helper.rbに自作のメソッドを作れる。
これがカスタムヘルパー
呼び出しはビューファイルの<% %>に埋め込み。(ERB: Embedded RuBy)
##Rails console
Rails consoleで文字列、演算、比較、条件分岐について学びました。
オブジェクト指向ってこーいうことか!がうっすらつかめると思います。
puts "文字列"
を叩くと、結果は
文字列
=> nil
このnilはなんやねん。と思ったらputsは返り値にnilを取り、
スクリーンに文字列を表示する命令らしい。(標準出力です)
##Rubyで作ったカスタムヘルパー
module ApplicationHelper
# ページごとの完全なタイトルを返します。 # コメント行
def full_title(page_title = '') # メソッド定義とオプション引数
base_title = "Ruby on Rails Tutorial Sample App" # 変数への代入
if page_title.empty? # 論理値テスト
base_title # 暗黙の戻り値
else
page_title + " | " + base_title # 文字列の結合
end
end
end
このコードがすらすら読めるようになってました!チュートリアルすげえ!!
##ブロック
パターン①
(1..5).each { |i| puts i }
の{ }
ここがブロック。| |
で囲まれてんのがブロック変数。
パターン②
(1..5).each do |i|
puts i
end
do ~ end間がブロック。
奥が深く、よく出てくる記法なのでRailsやりながら覚えます。
##こんなコードもわかるようになった!
<%= stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload' %>
Rubyのメソッド呼び出し省略部分
①stylesheet_link_tagはメソッド名。Rubyは呼び出しに()いらない。
②メソッドの最後の引数がハッシュなら省略できる。
{media: 'all', 'data-turbolinks-track': 'reload'}
こっからハッシュ消した。
③Rubyは改行を気にしない。スペースだべ?と思ってる。
このメソッドが読み込まれると、次のHTMLが出力される。
<link data-turbolinks-track="true" href="/assets/application.css"
media="all" rel="stylesheet" />
#第5章
レイアウトを作成する。見た目に関する技術をさらっと学んでいく。
HTMLとCSS、Bootstrap、Sassも扱っている。
##リンク
Railsでは<a>
タグを生成する
<%= link_to "リンク名", "リンク先" %>
というERBを利用できる。これは<a link="リンク先">リンク名</a>
というHTMLを生成してくれる。
<%= yield %>
ここにはURLごとにメインとなるコンテンツが入る。Railsチュートリアルのフォルダ階層でいうなら、
sample_app/app/views/static_pages/
に入っているビューファイルがそう。
アクセスしたURLによってルーティング、該当したコントローラーからアクションが呼び出され、アクションに対応したビューファイルがこの<%= yield %>
に組み込まれてブラウザに返ってくる。
##image_tagとアセットパイプライン
Railsアプリにはassetsというフォルダがある。中身はjavascriptsだったりstylesheetsだったりする。assetsの役目はサイト表示等の高速化、ユーザーの体感を向上させることである。
要するにassetsにjavascriptやcss,imageを入れておくと、これらファイルを統合してくれる。ブラウザから見たときに、ファイルが細分化されているのは不都合らしく、乱暴に言えば一つのファイルにまとまっているほうがいいみたい。一方、人から見た場合、一つのファイルにまとめられると管理がしにくい。
そこでRailsでは、人にもブラウザにも優しいassetsという仕組みを実装している。
image_tag
はassets/imagesからファイルを探してimageタグを作成する。
image_tag("ファイル名", alt: "画像だよ")
生成されるimageタグは
<img alt="画像だよ" src="/assets/rails-9308b8f92fea4c19a3a0d83854526.png" />
アセットパイプラインを通じるのでsrc属性がassets/images/ではなく/assetsから始まっている。
##パーシャル
HTMLファイルを切り分けることで見やすくする。
HTMLのヘッダー部分を切り分けて別ファイルに移動し、名前を_
から始まる任意名にして拡張子を.html.erb
にしておく。
呼び出しは下にかいてあるコードでおこなう。
<%= render "layouts/hoge" %>
でapp/views/layouts/_hoge.html.erb
を探し出して代入してくれる。
#第6章
この章ではユーザー用のデータモデルを作り、データを保管できるようにする。
modelを作成して、DBも作るのでこの章以降いっきにアプリらしい仕組みができあがる。
##リレーショナルデータベース
Rubyではattr_accessor
メソッドをつかいUserモデルの属性を定義していました。
attr_accessorメソッドにより、クラス内のインスタンス変数に値を代入したり(attr_write)、値を取り出したり(attr_read)していました。
一方、RailsではActiveRecordによってリレーショナルデータベースに値を保管するので、上で述べたようなRuby式のUserモデル定義が必要ありません。
Rubyは、Class内のメソッド、インスタンス変数でデータを保管する。
Railsは、リレーショナルデータベースにActiveRecordで保管する。
##Userモデルの生成
$ rails generate model User name:string email:string
これでマイグレーションファイルを作成する。
コントローラ名には複数形を使い、モデル名には単数形を用いる。コントローラはUsersでモデルはUserです。
出来上がったマイグレーションファイルをDBに反映するために
$ rails db:migration
これでUserのデータモデルがDBにできあがっています。
##Userクラスのスーパークラスとスーパークラススーパークラス
Userモデルのファイルを見ると
class User < ApplicationRecord
end
UserクラスはApplicationRecordを継承している。ApplicationRecordのスーパークラスはApplicationRecord::BaseでこのクラスのメソッドをUserクラスでも使うことが出来る。
たとえば、User.new
で空のUserインスタンスを生成。.valid?
メソッドでオブジェクトが有効かを調べられる。
user = User.new(name: "hoge", email: "hoge@hoge.com"
user.valid?
=>true
user.save
でDBにオブジェクトの情報を保存する。
user.update_attributes
で属性のハッシュを更新して保存する。
i) saveメソッドで更新
user.name = "abe"
user.email = "abe@abe.com"
user.save
ii) update_attributesメソッドで更新
user.update_attributes(name: "abe", email: "abe@abe.com")
update_attribute
なら特定の属性を変更できる。おまけでvalidationに引っかからないらしい。
##Validationのテスト
$ rails generate model User
がついでにUserモデル用のテストファイル`も実装してくれる。
$ rails test:model
でモデルに関するテストのみを走らせられる。
name属性にpresence(存在性)の検証をかけた。この場合のテストは以下になる。
test "name should be present" do
@user.name = " "
assert_not @user.valid?
end
① @user.nameに空白を代入し、@user.valid?で有効かどうかを問う。
② validation: presenceの条件なので、返答はfalseである。
③ assert_notは与えた条件がfalseならGreenになる。
##DBのレベルでの一意性
ActiveRecordのvalidationは、DBのレベルでは効かない。DBに入れるときにだけ有効性を確認するから。DBレベルでも一意性を保つ方法はDBのインデックスを利用することである。
###まずはインデックスから
DBを検索するときの索引機能。それがインデックス。この機能をDBの任意のカラムに適用すると、検索を高速化してくれる。
###このインデックスに一意性をもたせる
インデックスは検索を高速化するための索引だが、これに一意性をもたせることができる。これでDBレベルで一意性を保つことができる。
###Railsでどうやってインデックスに一意性をもたせるのか
DBをいじるので、migrationファイルを作成する。email属性に優位性のあるインデックスを作成したいと仮定すると
$ rails generation migration add_index_to_users_email
のコマンドで未定義のマイグレーションファイルを作成して、このファイルの中身を以下のようにする。
class AddIndexToUsersEmail < ActiveRecord::Migration[5.0]
def change
add_index :users, :email, unique: true
end
end
add_index (テーブル名), (カラム名), unique:true
これで最後に
$ rails db:migrate
###長過ぎるので続きは別の投稿に。現在第7章勉強中