techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

Rails Tutorial マイクロポストアプリを作る

Rails Tutorial マイクロポストアプリを作る

Toy アプリケーション

  • Railsアプリケーションの概要を素早くつかむ
    • scaffoldジェネレータ
      • 大量の機能を自動的に生成するスクリプト
  • RESTアーキテクチャについて考察

本書の目的は、scaffoldを使用した即席のアプローチによる表面的な理解ではなく、そこを突破してRailsを深いレベルまで理解することにあります。

このチュートリアルでは、とりあえず scaffold で「魔法」のように簡単に作っ後で同等の機能を1つ1つ手動で作成して解説する、らしい。

作るのは Twitter のようなもの。

ベース作成

rails new する。

$ cd ~/workspace
$ rails _5.0.0.1_ new toy_app
$ cd toy_app/

Rails 5 を使用するのでバージョン指定が異なる。
Gemfile の内容は Hello, world の時と同じ。

bundle install する。

$ bundle install --without production
Fetching gem metadata from https://rubygems.org/
Fetching version metadata from https://rubygems.org/
Fetching dependency metadata from https://rubygems.org/
Resolving dependencies...
Using rake 11.2.2
Using concurrent-ruby 1.0.2
Using i18n 0.7.0
Using minitest 5.9.0
Using thread_safe 0.3.5
Using builder 3.2.2
Using erubis 2.7.0
Using mini_portile2 2.1.0
Using pkg-config 1.1.7
Using rack 2.0.1
Using nio4r 1.2.1
Using websocket-extensions 0.1.2
Using mime-types-data 3.2016.0521
Using arel 7.1.1
Using bundler 1.12.5
Using byebug 9.0.0 (was 9.0.5)
Using coffee-script-source 1.10.0
Using execjs 2.7.0
Using method_source 0.8.2
Using thor 0.19.1
Using debug_inspector 0.0.2
Using ffi 1.9.14
Using multi_json 1.12.1
Using rb-fsevent 0.9.7
Using puma 3.4.0 (was 3.6.0)
Using sass 3.4.22
Using tilt 2.0.5
Using spring 1.7.2
Using sqlite3 1.3.11
Using turbolinks-source 5.0.0
Using tzinfo 1.2.2
Using nokogiri 1.6.8
Using rack-test 0.6.3
Using sprockets 3.7.0
Using websocket-driver 0.6.4
Using mime-types 3.1
Using coffee-script 2.4.1
Using uglifier 3.0.0 (was 3.0.2)
Using rb-inotify 0.9.7
Using turbolinks 5.0.1
Using activesupport 5.0.0.1
Using loofah 2.0.3
Using mail 2.6.4
Using listen 3.0.8
Using rails-dom-testing 2.0.1
Using globalid 0.3.7
Using activemodel 5.0.0.1
Using jbuilder 2.4.1 (was 2.6.0)
Using rails-html-sanitizer 1.0.3
Using spring-watcher-listen 2.0.0
Using activejob 5.0.0.1
Using activerecord 5.0.0.1
Using actionview 5.0.0.1
Using actionpack 5.0.0.1
Using actioncable 5.0.0.1
Using actionmailer 5.0.0.1
Using railties 5.0.0.1
Using sprockets-rails 3.2.0
Using coffee-rails 4.2.1
Using jquery-rails 4.1.1 (was 4.2.1)
Using web-console 3.1.1 (was 3.3.1)
Using rails 5.0.0.1
Using sass-rails 5.0.6
Bundle complete! 16 Gemfile dependencies, 63 gems now installed.
Gems in the group production were not installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.

あとは bitbucket に新しいリポジトリ作成して push と、heroku create して push 。

  • ユーザのモデル設計 | column | type | |--------|--------| |id | integer| |name |string | |email |string |

  • マイクロポストのモデル設計 | column | type | |--------|--------| | id |integer | |content | text | |user_id |integer |

user_id 属性を使用して、1人のユーザーに複数のマイクロポストが関連付ける。

scaffold

Users リソースを scaffold ジェネレータで生成。
以下のコマンドで生成可能。
id ねーじゃん、と思ったら

なお、idパラメータはRailsによって自動的に主キーとしてデータベースに追加されるため、追加不要です

ですって。

$ rails generate scaffold User name:string email:string
Running via Spring preloader in process 5282
      invoke  active_record
      create    db/migrate/20160904230336_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
      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
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.coffee
      invoke    scss
      create      app/assets/stylesheets/users.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss

データベースのマイグレート

はい、ここで Rails 5 での差分。
Rails 5 から rake コマンドが rails コマンドに一本化されたので、以下のコマンドになる。

$ rails db:migrate
== 20160904230336 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0020s
== 20160904230336 CreateUsers: migrated (0.0029s) =============================

これでデータベースが更新され、usersデータモデルができる。

Rake

In the Unix tradition, the Make utility has played an important role in building executable programs from source code. Rake is Ruby make, a Make-like language written in Ruby.

ですって。もう使うことなさそうだけど。

ユーザ管理画面

なんと上記だけでユーザ情報の登録、閲覧、削除機能が備わっている。

URL アクション 用途
/users index すべてのユーザーを表示するページ
/users/1 show id=1のユーザーを表示するページ
/users/new new ユーザーを新規作成するページ
/users/1/edit edit id=1のユーザーを編集するページ

(削除要求は JavaScript でリクエスト発行してるとかなんとか)

マイクロポスト管理画面

$ rails generate scaffold Micropost content:text user_id:integer
Running via Spring preloader in process 2217
      invoke  active_record
      create    db/migrate/20160908221345_create_microposts.rb
      create    app/models/micropost.rb
      invoke    test_unit
      create      test/models/micropost_test.rb
      create      test/fixtures/microposts.yml
      invoke  resource_route
       route    resources :microposts
      invoke  scaffold_controller
      create    app/controllers/microposts_controller.rb
      invoke    erb
      create      app/views/microposts
      create      app/views/microposts/index.html.erb
      create      app/views/microposts/edit.html.erb
      create      app/views/microposts/show.html.erb
      create      app/views/microposts/new.html.erb
      create      app/views/microposts/_form.html.erb
      invoke    test_unit
      create      test/controllers/microposts_controller_test.rb
      invoke    helper
      create      app/helpers/microposts_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/microposts/index.json.jbuilder
      create      app/views/microposts/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/microposts.coffee
      invoke    scss
      create      app/assets/stylesheets/microposts.scss
      invoke  scss
   identical    app/assets/stylesheets/scaffolds.scss

ここでも Rails 5 での差分。
Rails 5 から rake コマンドが rails コマンドに一本化されたので、以下のコマンドになる。

$ rails db:migrate
== 20160908221345 CreateMicroposts: migrating =================================
-- create_table(:microposts)
   -> 0.0089s
== 20160908221345 CreateMicroposts: migrated (0.0091s) ========================

config/routes.rb を以下のように書き換える。

Rails.application.routes.draw do
  resources :microposts
  resources :users
  root 'application#hello'
end

これで /microposts/new にブラウザからアクセスするとマイクロポストを作成する画面が表示される。

validates

Railsでは、検証 (validates) を使用して簡単にこのような入力制限を追加することができます。

ということで最大入力文字数を決めてそれを超えている場合にエラー表示する機能を使ってみる。

app/models/micropost.rb を以下のように変更する。

class Micropost < ActiveRecord::Base
  validates :content, length: { maximum: 140 }
end

140 文字を超えるマイクロポストを作成しようとするとエラーが表示されるようになる。
非常に簡単に設定できて便利。他にはどんなのが使えるんじゃろかと思ったらあるわあるわ。

Active Record Validations — Ruby on Rails Guides

これは便利そう。

ユーザとマイクロポストの関連付け

1人のユーザーに対し複数のマイクロポストを関連付ける例。

app/models/user.rb に以下を

class User < ActiveRecord::Base
  has_many :microposts
end

app/models/micropost.rb にいかを記載する。

class Micropost < ActiveRecord::Base
  belongs_to :user
  validates :content, length: { maximum: 140 }
end

has_many, belongs_to でRailsとActive Recordがマイクロポストとユーザーを関連付けることができる、と。

これでテーブル上での関連は出来上がっている。
ユーザーに関連付けられたマイクロポストを表示する、というのは 第11章、第12章でやるとのことで、ここではひとまず console で紐付けして動作を確認するのみ。

$ rails console
Running via Spring preloader in process 2360
Loading development environment (Rails 5.0.0.1)

これでRailsアプリケーションを対話的に操作することができる。
DB内の、ユーザに紐づけられたマイクロポストを見てみる。

まずユーザを一人取り出す。

2.3.0 :001 > first_user = User.first
  User Load (0.4ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
 => #<User id: 1, name: "hoge", email: "hoge@hogehoge", created_at: "2016-09-05 15:54:04", updated_at: "2016-09-05 15:55:46">

そのユーザに紐付いたマイクロポストを表示。

2.3.0 :002 > first_user.microposts
  Micropost Load (0.3ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ?  [["user_id", 1]]
 => #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 1, content: "First micro post!", user_id: 1, created_at: "2016-09-08 22:21:48", updated_at: "2016-09-08 22:21:48">, #<Micropost id: 2, content: "Second micropost", user_id: 1, created_at: "2016-09-08 22:22:28", updated_at: "2016-09-08 22:22:28">]>

マイクロポストが紐付いていることがわかる。
次にマイクロポストに紐付いたユーザを見てみる。
先ほど取り出したマイクロポストの中から一つ取り出す。

2.3.0 :003 > micropost = first_user.microposts.first
 => #<Micropost id: 1, content: "First micro post!", user_id: 1, created_at: "2016-09-08 22:21:48", updated_at: "2016-09-08 22:21:48">

マイクロポストに紐付いたユーザを表示する。

2.3.0 :004 > micropost.user
 => #<User id: 1, name: "hoge", email: "hoge@hogehoge", created_at: "2016-09-05 15:54:04", updated_at: "2016-09-05 15:55:46">

きちんと紐づけられて保存されていることがわかる。

Scaffold機能でお手軽にマイクロポストアプリが実装できた。

自動生成されたコードが何をやっているか、が次章以降でわかるということで引き続き。