Laravel経験者が「Rails チュートリアル」流し読みする
※特に明示しない限り、引用は全てRailsチュートリアルからの引用を示しています
1章開始
- Railsをインストールしたい時:gemを使う
- bundlerをインストールしたい時:gemを使う
- Yarnとは何:JavaScript依存関係マネージャ
- Webpackerとは何:フロントエンドビルドシステム。Rails用。「JavaScript」「CSS」「画像やフォント」といった静的アセットを管理。
1章終了
2章開始
$ bundle _2.2.17_ config set --local without 'production'
$ bundle _2.2.17_ install
パッケージインストール用のコマンド。 --local without 'production'
で開発用のパッケージをインストールできる
$ rails webpacker:install
rails の webpacker install コマンド。なんでrailsからインストール?これはプロジェクト毎にインストールするタイプのライブラリなのかな?
プロジェクト毎にバージョン違ったりする?
class ApplicationController < ActionController::Base
def hello
render html: "hello, world!"
end
end
rails のコントローラ側でのレンダリング処理。
文法違うだけ。viewの読み込みについては後述。
命名
app/controllers/application_controller.rb
こんな感じでスネークケース(そういやそうだったな)
Laravelとベストプラクティス違いそう。
RoR用の命名規則表などあると思うのであとで調べる。
scaffold実行コマンド。めっちゃ関連ファイル吐いてる。すご。
testまで、、、素晴らしい。
$ rails generate scaffold User name:string email:string
invoke active_record
create db/migrate/20190820002503_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
invoke resource_route
route resources :users
invoke scaffold_controller
create app/controllers/users_controller.rb
invoke erb
create app/views/users
create app/views/users/index.html.erb
create app/views/users/edit.html.erb
create app/views/users/show.html.erb
create app/views/users/new.html.erb
create app/views/users/_form.html.erb
invoke test_unit
create test/controllers/users_controller_test.rb
create test/system/users_test.rb
invoke helper
create app/helpers/users_helper.rb
invoke test_unit
invoke jbuilder
create app/views/users/index.json.jbuilder
create app/views/users/show.json.jbuilder
create app/views/users/_user.json.jbuilder
invoke assets
invoke scss
create app/assets/stylesheets/users.scss
invoke scss
create app/assets/stylesheets/scaffolds.scss
詳細はまだ踏み入らない。
慣れてから。
migrateコマンド。ほぼ Laravel と一緒
$ rails db:migrate
(:usersという一見奇妙な記法は、Ruby言語特有の「シンボル」と呼ばれるものです。詳細については4.3.3で説明します)。
シンボルなるものが存在すると、、、少しだけ頭に入れておく。
root 'application#hello'
ルーティングの時にアクションを指定する場合は#のあとにアクション名を記載。Laravelとほぼ同じ。
Rails.application.routes.draw do
resources :users // こいつ気になる。
root 'users#index'
end
class UsersController < ApplicationController
.
.
.
def index
@users = User.all
end
.
.
.
end
User.all
が噂のあれ(Active Record)か。これはすごい。
下のコントローラーとビューの例だと変数の渡し方明示していないよね?
@記号で始まる変数をRubyではインスタンス変数と呼び、Railsのコントローラ内で宣言したインスタンス変数はビューでも使えるようになります。
らしい。すご。
app/controllers/users_controller.rb
class UsersController < ApplicationController
.
.
.
def index
@users = User.all
end
.
.
.
end
app/views/users/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Users</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.email %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete,
data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New User', new_user_path %>
2.3Micropostsリソースまで。飯たべる
Rails.application.routes.draw do
resources :microposts
resources :users
root 'users#index'
end
resourceの定義の仕方
class Micropost < ApplicationRecord
validates :content, length: { maximum: 140 }
end
ここの記法気になるな。。。validation調べよう
全体的に記法がタイプ数少なくて済みそう
リレーション、バリデーションは特に困ることもなさそう
2章終了
3章はじめ
Gemfileはパッケージ管理のためのファイル。バージョンとパッケージ名を指定する。
1.4.4で学んだことを思い出しましょう。Gitを使う場合は、masterブランチでずっと作業するのではなく、その都度トピックブランチを作成して作業するのがよい習慣です。Gitでバージョン管理を行っているのであれば、次のコマンドを実行して、静的なページ用のトピックブランチをチェックアウトしましょう。
~Rails チュートリアル
大事
一般的なシナリオの1つは、生成したコードを元に戻したい場合です。例えばコントローラを生成した後で、もっといいコントローラ名を思い付き、生成したコードを削除したくなった場合などです。リスト 3.7のように、Railsはコントローラ以外にも関連ファイルを大量に生成するので、生成されたコントローラファイルを削除するだけでは元に戻りません。自動生成されたコードを元に戻すためには、新規作成されたファイルを削除するだけではなく、既存のファイルに挿入されたコードも削除する必要があります(実際、2.2や2.3でも説明したように、rails generateを実行するとルーティングのroutes.rbファイルも自動的に変更されるので、これも元に戻さなくてはなりません)。このようなときは、「generate」という言葉に因んで、rails destroyというコマンドを実行することで元に戻すことができます。例えば次の2つのコマンドは、自動生成と、それに対応する取り消し処理の例です。
~Rails チュートリアル
はぇ~確かにそういうコマンドが間違えた時大変だもんなぁ。関連ファイル多すぎて
Routing
get 'static_pages/home'
スラッシュで記述するとStaicPagesコントローラのhomeアクションとを紐づける。
StaticPagesコントローラは一般的なRESTアクションに対応していないことに注意してください。これは、静的なページの集合に対しては、適切なアクションと言えます。言い換えると、RESTアーキテクチャは、あらゆる問題に対して最適な解決方法であるとは限らないということです。
Rails チュートリアル
RESTの利点はデータへの操作をURLで表現する能力が高いことなので、静的サイトだとそんなに。(削除とか更新とかしないから)
(たとえ何も書かれていなくても)Rails特有の振る舞いをします。具体的には、/static_pages/homeというURLにアクセスすると、RailsはStaticPagesコントローラを参照し、homeアクションに記述されているコードを実行します。その後、そのアクションに対応するビュー(1.3.3で説明したMVCのVに相当)を出力します。今回の場合、homeアクションが空になっているので、/static_pages/homeにアクセスしても、単に対応するビューが出力されるだけです。
rails チュートリアル
これすげぇ。ちょっと気味悪いけど笑
返り値返すー>その値を表示する
上記みたいなフローを明示的に書くのが普通だと思ってるから変な気分だ
アプリケーションのコードよりも明らかにテストコードの方が短くシンプルになる(=簡単に書ける)のであれば、「先に」書く
動作の仕様がまだ固まりきっていない場合、アプリケーションのコードを先に書き、期待する動作を「後で」書く
~ Rails チュートリアル
これ良いな。こういうやりかただとTDDやっても上手くいきそう。
全部最初にテスト書こうとすると「どうやるんだっけ???」みたいになりそうだし。
多くのテストツールでは、テストの失敗を red 、成功したときを green で表します。ここから、このサイクルを「 red ・ green ・ REFACTOR」
rails tutorial
これよく聞くやつ。
例では以下のテストからRedGreenRefactorを開始してる。
結構以外だ。もっと細かくテスト定義してくもんかと。
その辺のバランス感覚覚えないとな
test "should get about" do
get static_pages_about_url
assert_response :success
end
3.4少しだけ動的なページまで
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
test "should get home" do
get static_pages_home_url
assert_response :success
assert_select "title", "Home | Ruby on Rails Tutorial Sample App"
end
test "should get help" do
get static_pages_help_url
assert_response :success
assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
end
test "should get about" do
get static_pages_about_url
assert_response :success
assert_select "title", "About | Ruby on Rails Tutorial Sample App"
end
end
このへんのテストの記法よーわからん。
特に「get static_pages_about_url」とかのurlの記述。
どういう法則なんだこれ。
コントローラ名+アクション名+_url でいいんかな?
そうっぽい。
<% provide(:title, "Home") %>
<!DOCTYPE html>
<html>
<head>
<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
</head>
<body>
<h1>Sample App</h1>
<p>
This is the home page for the
<a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</p>
</body>
</html>
ビューのあたりの記法に関して。
<% provide(:title, "Home") %>
これだと値を表示しない。
<%= yield(:title) %>
これだと値を表示する。
3.4.3レイアウトと埋め込みRuby(Refactor)まで
<% provide(:title, "The Title") %>
<!DOCTYPE html>
<html>
<head>
<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
</head>
<body>
Contents
</body>
</html>
yield, provide ペアで使う。
yield は挿入される場所と名前を示す。
provide はどこに挿入するかを示す。
<!DOCTYPE html>
...
<body>
<%= yield %>
</body>
</html>
引数なしの yield を呼び出すとページの内容を挿入する箇所を指定できる。
基本的にbody直下とかcontainer直下とかで使う。Laravelと一緒。
root 'application#hello'
こんなかんじでhome(uri + '/' でアクセスしたとき)のアクションを指定できる
Rubyにおいてnilは特別なオブジェクトです。Rubyのオブジェクトのうち、オブジェクトそのものの論理値がfalseになるのは、false自身とnilの2つしかありません。
その他のあらゆるRubyのオブジェクトは、ゼロですらtrueです。
〜rails チュートリアル
ゼロもtrueか。。。PHPerは混乱しそう😅
ここで、Rubyのメソッドには「暗黙の戻り値がある」ことにご注意ください。これは、メソッド内で最後に評価された式の値が自動的に返されることを意味します
~ railsチュートリアル
面白いな。楽だ。
そのメソッドに対応する「破壊的」メソッドを使います。破壊的メソッドの名前には、元のメソッドの末尾に「!」を追加したものを使うのがRubyの慣習です。
なるほど。これだとわかりやすくて良いな。(と思うと同時に値ぐりぐりやるときは!だらけになるのかな?🤔)
>> 0..9
=> 0..9
>> 0..9.to_a # おっと、9に対してto_aを呼んでしまっていますね
NoMethodError: undefined method `to_a' for 9:Fixnum
>> (0..9).to_a # 丸カッコを使い、範囲オブジェクトに対してto_aを呼びましょう
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range を使うときは注意。全部に丸括弧付けておくのが無難?
1つの重要な違いとして、ハッシュでは要素の「並び順」が保証されないという点があります 。もし要素の順序が重要である場合は、配列を使う必要があります。
へぇ並び順保証されないのか。なんか気持ち悪いな(連想配列とは別物...?)
ハッシュテーブル的なもののほうが概念としては近いかな
名前ハッシュだし
# メソッド呼び出しの丸カッコは省略可能。
stylesheet_link_tag('application', media: 'all',
'data-turbolinks-track': 'reload')
# 上は以下のように書いても同じ
stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload'
# 最後の引数がハッシュの場合、波カッコは省略可能。
stylesheet_link_tag 'application', { media: 'all',
'data-turbolinks-track': 'reload' }
# 上は以下のように書いても同じ
stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload'
記法が面白い。変な感じする
>> class Word < String # WordクラスはStringクラスを継承する
>> # 文字列が回文であればtrueを返す
>> def palindrome?
>> self == self.reverse # selfは文字列自身を表します
>> end
>> end
=> :palindrome?
Stringを継承する
美しい
>> class String
>> # 文字列が回文であればtrueを返す
>> def palindrome?
>> self == self.reverse
>> end
>> end
=> :String
>> "deified".palindrome?
=> true
String を拡張する
大丈夫なの。。。?
やっぱあんまりよくないみたい
get 'static_pages/help'
↓
get '/help', to: 'static_pages#help'
任意のアクションに送るコード
require 'test_helper'
class SiteLayoutTest < ActionDispatch::IntegrationTest
test "layout links" do
get root_path
assert_template 'static_pages/home'
assert_select "a[href=?]", root_path, count: 2
assert_select "a[href=?]", help_path
assert_select "a[href=?]", about_path
assert_select "a[href=?]", contact_path
end
end
統合テスト例
7章まで
<li id="micropost-<%= micropost.id %>">
こんな感じでidを振っておくと後で便利。
13.3.2マイクロポストを作成する
上のエラーメッセージようわからんんん
Micropost.where("user_id = ?", id)
上の疑問符があることで、SQLクエリに代入する前にidがエスケープされるため、SQLインジェクション(SQL Injection)呼ばれる深刻なセキュリティホールを避けることができます。
セキュリティ
class User < ApplicationRecord
has_many :microposts, dependent: :destroy
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
.
.
.
end
has many relation
resources :users do
collection do
get :tigers
end
end
このコードは /users/tigers というURLに応答します(アプリケーションにあるすべてのtigerのリストを表示します)8 。
なにこれ?どういう仕組?
この解説がわかりやすい。
member は特定のデータに対するアクションに利用します。
collection は全部のデータに対するアクションに利用します。
~【Ruby on Rails】ルーティング member と collection の違い
14.2.2統計と[Follow]フォーム madef