Posted at

Rails Tutorialsで勉強のメモ その2

More than 5 years have passed since last update.

デモアプリケーションをscaffoldジェネレータですばやく作成


デモアプリの準備

# デモアプリの初期化

$ cd rails_projects
$ rails new demo_app
$ cd demo_app

# Gemfileの書き換え
$ vim Gemfile


Gemfile

source 'https://rubygems.org'

ruby '2.0.0'
#ruby-gemset=railstutorial_rails_4_0

gem 'rails', '4.0.4'

group :development do
gem 'sqlite3', '1.3.8'
end

gem 'sass-rails', '4.0.2'
gem 'uglifier', '2.1.1'
gem 'coffee-rails', '4.0.1'
gem 'jquery-rails', '3.0.4'
gem 'turbolinks', '1.1.1'
gem 'jbuilder', '1.0.2'

group :doc do
gem 'sdoc', '0.3.20', require: false
end

group :production do
gem 'pg', '0.15.1'
gem 'rails_12factor', '0.0.2'
end


# gemのインストール

$ bundle install --without production
$ bundle update
$ bundle install

# gitリポジトリの作成とコミット
$ git init
$ git add .
$ git commit -m "Initial commit"

# GitHubにpush
# 事前にGitHubにdemo_appというリポジトリを作成
$ git remote add origin https://asam-3@github.com/asam-3/demo_app.git
$ git push -u origin master


モデル設計



  • マイクロブログのモデル


    • ブログのユーザ

    • マイクロポスト



  • usersデータモデル


列名

備考

id
integer
一意のキー

name
string

email
string


  • micropostsデータモデル

列名

備考

id
integer
一意のキー

content
string

user_id
integer


Usersリソース


  • UsersデータモデルとWebインタフェースが組み合わさったもの

  • ユーザをHTTPプロトコル経由で自由に作成/読み出し/更新/削除できるオブジェクト


  • scaffoldジェネレータでUsersリソースを生成する



    • rails generateスクリプトにscaffoldコマンドを渡す



# Usersリソースを作成(Usersデータモデルが作成される)

$ rails generate scaffold User name:string email:string

# データベースをmigrateし、usersデータモデルを作成する
# bundle execを使用するのは、現在のGemfileに対応するバージョンのRakeが確実に実行されるようにするため
$ bundle exec rake db:migrate

# サーバを起動
$ rails s


参考:rakeコマンドについて


  • Ruby版のmakeのようなもの

# rakeのデータベースタスクを参照

$ bundle exec rake -T db
rake db:create # Create the database from DATABASE_URL or conf...
rake db:drop # Drops the database using DATABASE_URL or the ...
rake db:fixtures:load # Load fixtures into the current environment's ...
rake db:migrate # Migrate the database (options: VERSION=x, VER...
rake db:migrate:status # Display status of migrations
rake db:rollback # Rolls the schema back to the previous version...
rake db:schema:cache:clear # Clear a db/schema_cache.dump file
rake db:schema:cache:dump # Create a db/schema_cache.dump file
rake db:schema:dump # Create a db/schema.rb file that can be portab...
rake db:schema:load # Load a schema.rb file into the database
rake db:seed # Load the seed data from db/seeds.rb
rake db:setup # Create the database, load the schema, and ini...
rake db:structure:dump # Dump the database structure to db/structure.sql
rake db:version # Retrieves the current schema version number
rake test:all:db # Run tests quickly, but also reset db

# rakeの全てのタスクを参照
$ bundle exec rake -T
(省略)


ユーザページの表示



  • rails generate scaffold UserでUsersリソースを作成すると、ページも自動生成される

URL
アクション
用途

/users
index
全てのユーザ一覧を表示

/users/1
show
id=1のユーザを表示

/users/new
new
新規ユーザを作成

/users/1/edit
edit
id=1のユーザを編集



  • ユーザ関連操作を一通り実施


    • 作成

    • 表示

    • 編集

    • 削除




  • RailsにおけるMVCの挙動(/usersにアクセスした際のフロー)


    1. /usersというURLへのリクエストを発行

    2. Railsルータが/usersをUsersコントローラ内のindexアクションに割り当てる(ルーティング)

    3. indexアクションは、Userモデルに「全てのユーザを取得する」と指示する(User.all)

    4. Userモデルは全てのユーザをDBから取り出す

    5. Userモデルはユーザの一覧をコントローラに返す

    6. コントローラはユーザの一覧を@users変数に保存し、indexビューに渡す

    7. ビューはコードの中に埋め込まれているRubyを使用してHTMLを生成する

    8. コントローラは生成されたHTMLをブラウザに返す




  • Railsルータのソース


    • URLをUsersリソースで使用するコントローラアクションにマッピング

    • URLとアクションの組合せを作成




config/routes.rb

DemoApp::Application.routes.draw do

resources :users
end


  • scaffoldで生成したコントローラ


    • Usersのアクションがまとめられている




app/controllers/users_controller.rb(クラス・メソッド定義のみ)

class UserController < ApplicationController

# 全てのユーザを表示するページ
def index
end

# ユーザを表示するページ
def show
end

# ユーザを新規作成するページ
def new
end

# ユーザを作成するアクション
def create
end

# ユーザを編集するページ
def edit
end

# ユーザを更新するアクション
def update
end

# ユーザを削除
def destroy
end
end



  • UsersコントローラとUserモデルの関係を確認


    • indexアクション


      • Userモデルから全てのユーザの一覧を取り出し、@users変数に格納






app/controllers/users_controller.rb(indexメソッドのみ)

class UserController < ApplicationController

def index
@users = User.all
end
end


  • Userモデル


    • 継承やActiveRecordライブラリにより、UserモデルはUser.allというリクエストに対して全てのユーザを返すことができる




app/models/user.rb(Userモデル)

class User < ActiveRecord::Base

end


  • ユーザーのビュー



    • @users変数に一覧が保存されると、コントローラが下記のビューを呼び出す




app/views/users/index.html.erb

<h1>Listing users</h1>

<table>
<tr>
<th>Name</th>
<th>Email</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @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 %>
</table>
<br />
<%= link_to 'New User', new_user_path %>


  • Usersリソースの問題


    • データのバリデーションチェックが行われていない

    • ユーザ認証がない

    • テストコードがほぼない

    • レイアウトがちょっと

    • 理解しにくい




Micropostsリソース


マイクロポストのページを表示

# scaffoldでMicropostを作成

$ rails generate scaffold Micropost content:string user_id:integer

# 新しいデータモデルでDBを更新
$ bundle exec rake db:migrate



  • Micropostを追加したことによるソースの追加/変更


    • RailsルータにMicropostsが追加される


    • MicropostsControllerなど、Usersと同様に各種ファイルの作成



  • とりあえずマイクロポストをブラウザから2個作ってみる


config/routes.rb

DemoApp::Application.routes.draw do

resources :microposts

resources :users
end



文字数制限の追加



  • validatesを使用して入力制限を追加

  • micropostモデルに入力制限のロジックを追加


    • 140文字以内




app/models/micropost.rb

class Micropost < ActiveRecord::Base

validates :content, length: { maximum: 140 }
end


UserとMicropostの関連付け


  • 一人のユーザに対して複数のマイクロポストを関連付ける


    • has_many :microposts



  • 一つのマイクロポストは一つのユーザにのみ属する


    • belongs_to :user




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


Railsアプリケーションの対話的な操作(rails console


  • Railsのconsole


    • Railsアプリケーションを対話的に操作


    • rails consoleで起動




  • UserMicropostの関連付けを確認

$ rails console

# first_user変数に一人目のユーザを設定
> first_user = User.first
User Load (0.6ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
=> #<User id: 2, name: "テストユーザー", email: "admin@localhost", created_at: "2014-08-02 06:36:09", updated_at: "2014-08-02 06:36:09">

# ユーザに関連付けられているマイクロポストを参照
> first_user.microposts
Micropost Load (2.4ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? [["user_id", 2]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 1, content: "テスト", user_id: 2, created_at: "2014-08-02 06:34:54", updated_at: "2014-08-02 06:35:06">]>

# コンソールを終了
> exit


継承の階層


モデルの継承構造



  • ActiveRecord::Baseクラスを継承


    • 作成したオブジェクトはDBにアクセスできるようになり、DBのカラムをRubyの属性のように扱えるようになる




コントローラの継承構造



  • ApplicationControllerを継承


  • ApplicationControllerActionController::Baseを継承


    • モデルオブジェクトの操作

    • インバウンドHTTP requestのフィルタ

    • ビューをHTMLとして出力



  • Railsのコントローラは必ずApplicationControllerを継承


    • Applicationコントローラで定義した内容は全てのアプリケーションに反映される

    • サインイン・サインアウトのヘルパーメソッドを定義する、といった用途に使用できる




デモアプリケーションのデプロイ


  • リポジトリをGitHubに登録

$ git add .

$ git commit -m "Finish demo app"
$ git push


  • Herokuにデプロイ

$ heroku create

$ git push heroku master


  • 本番DBのマイグレーション

$ heroku run rake db:migrate


まとめ


  • この章でやれたこと


    • Rails全体を高度なレベルで概観

    • MVCモデルを確認

    • RESTアーキテクチャに触れる

    • データベースモデルを作成

    • データベースを背後に持つWebアプリケーションを本番環境で動作させる