Status Code 303 - See Other

サーバサイド、iOS・アンドロイドアプリ、インフラレベルの話まで幅広くやってます。情報の誤りや指摘・意見などは自由にどうぞ。

Ruby on Rails チュートリアル2章

概要

Ruby の Web Framework である Ruby on Railsチュートリアルについてまとめる。
対象読者としては、チュートリアルを一度は読んだけどチュートリアルからいちいちコマンドなどを再確認するのが面倒な場合など。

チュートリアル
第1章 ゼロからデプロイまで | Rails チュートリアル

前回記事
Ruby on Rails チュートリアル1章 - Status Code 303 - See Other

使用環境

※ 全部基本的に無料

IDE (Integrated Development Environment)

Cloud 9 (Cloud9 - Your development environment, in the cloud)

  • クラウド上で作業できる開発環境、最近はこんなサービスもあるんですね・・
  • 基本的にコンソール上で作業するので、GUI しか使えない人は厳しいかも?
  • ファイルの編集には vi を使用

バージョン管理

Git

  • おなじみのバージョン管理ツール
  • SVN(subversion)との違いは、ローカルでも自由に作業できたり、ネット不通でも開発できる環境だったり。

Gitリポジトリ

Bitbucket

  • 少人数開発であればプライベート環境(他人に公開しない)が無料で使える。
  • Github と基本的に提供機能は同じ。

事前準備 (前回記事とほぼ同じ)

今回は、前回のアプリは扱わないため、新しくプロジェクトを作成する。
なお、今回は チュートリアルに習い、プロジェクト名を toy_app として記述する。

プロジェクト作成
$ cd ~/workspace
$ rails _4.2.2_ new toy_app
$ cd toy_app/
Gemfile 置換
$ rm ~/workspace/toy_app/Gemfile
$ vi ~/workspace/toy_app/Gemfile

以下をコピペで貼付けて作成。

source 'https://rubygems.org'

gem 'rails',        '4.2.2'
gem 'sass-rails',   '5.0.2'
gem 'uglifier',     '2.5.3'
gem 'coffee-rails', '4.1.0'
gem 'jquery-rails', '4.0.3'
gem 'turbolinks',   '2.3.0'
gem 'jbuilder',     '2.2.3'
gem 'sdoc',         '0.4.0', group: :doc

group :development, :test do
  gem 'sqlite3',     '1.3.9'
  gem 'byebug',      '3.4.0'
  gem 'web-console', '2.0.0.beta3'
  gem 'spring',      '1.1.3'
end

group :production do
  gem 'pg',             '0.17.1'
  gem 'rails_12factor', '0.0.2'
end
本番環境用のgemを除いたローカルgemをインストール
$ bundle install --without production
Gitの管理下におく
$ git init
$ git add -A
$ git commit -m "Initialize repository"
Bitbucket 登録

リボジトリ作成 (bitbucket のサイトで作成)
次に以下のコマンドで作成

$ git remote add origin git@bitbucket.org:${USER_NAME}>/toy_app.git
$ git push -u origin --all 
Applicationコントローラにhelloを追加
デフォルトページを変更する

2章内容(名前変更必要)

作成するデータ定義

ユーザ情報 (users)

  • id :integer
  • name :string
  • email :string

マイクロポスト (microposts)

  • id :integer
  • content :text
  • user_id :integer

Userリソース作成

Railsのscaffoldを用いて作成する。

$ rails generate scaffold User name:string email:string

Rakeを使用してデータベースをマイグレート(データベース更新・usersデータモデル作成)
※ rake db:migrate でもいける場合もあるがシステム依存らしい

$ bundle exec rake db:migrate

サーバ起動して追加リソースを見る

サーバ起動

ローカル

$ rails server  # ローカル環境
$ rails server -b $IP -p $PORT  # Cloud 9
リソース先にアクセス

下記のRestful APIが自動生成される。
アクセス可能なページ(URL)一覧

メソッドURLアクション用途
GET/usersindexすべてのユーザーを表示するページ
GET/users/1showid=1のユーザーを表示するページ
GET/users/newnewユーザーを新規作成するページ
GET/users/1/editeditid=1のユーザーを編集するページ
その他利用可能なアクション。
メソッドURLアクション用途
POST/userscreateユーザーを作成するアクション
PATCH/users/1updateid=1のユーザーを更新するアクション
DELETE/users/1destroyid=1のユーザーを削除するアクション

(筆者追記) 動作実行前との差分を知りたければ $ git status を実行する。

リソースの自動生成について

挙動説明

プログラムとDBがどのように連携しているかの説明。本記事は手順書的な意味合いが強いので割愛。

挙動確認・変更方法

上記リソースのアクセス先ルーティングを変更したい場合、routers.rbを変更する。

vi config/routes.rb
Rails.application.routes.draw do
  resources :users
  # The priority is based upon order of creation: first created -> highest priority.
  # See how all your routes lay out with "rake routes".

  # You can have the root of your site routed with "root"
  root 'users#index' # 'application#hello から変更
(以下省略)

もし、さきほどの Restful API の各挙動を知りたければ、app/controllers/users_controller.rb を参照する。

$ less app/controllers/users_controller.rb
自動生成したリソースの欠点
  • データ検証がされていない
  • 誰でも作成・参照・更新・削除可能
  • 業務要件を満たすテストが存在しない
  • レイアウトやスタイルはデフォルト
  • 理解が困難

micropostsリソース作成

microposts リソース作成

基本的にUserリソースと同じ。

$ rails generate scaffold Micropost content:text user_id:integer
$ bundle exec rake db:migrate
動作確認

挙動変更

マイクロポストの文字数に制限をかける。

vi app/models/micropost.rb
class Micropost < ActiveRecord::Base
  validates :content, length: { maximum: 140 }  # 追加
end

データモデル同士の関連付け

※ユーザとユーザ ID が一致した microposts を事前に作成しておくこと。

user.rb を編集する
$ vi app/models/user.rb
class User < ActiveRecord::Base
  has_many :microposts  # 追加
end
micropost.rb を編集する
vi app/models/micropost.rb
class Micropost < ActiveRecord::Base
  belongs_to :user  # 追加
  validates :content, length: { maximum: 140 }  # 追加
end
関連付け確認方法

rails console を使用して確認する。

$ rails console
>> first_user = User.first
>> first_user.microposts

コンソール実行例 (この例では、ユーザが二人いて二人目がデータ持っていた)

2.3.0 :003 > second_user = User.second
  User Load (0.4ms)  SELECT  "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 1 OFFSET 1
 => #<User id: 8, name: "XYZ", email: "xyz@aaa.com", created_at: "2016-07-02 07:37:50", updated_at: "2016-07-02 07:37:50"> 
2.3.0 :004 > second_user.microposts
  Micropost Load (0.3ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ?  [["user_id", 8]]
 => #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 2, content: "あああああ", user_id: 8, created_at: "2016-07-02 07:44:23", updated_at: "2016-07-02 07:44:23">, #<Micropost id: 3, content: "AAAAAAAAAAAA", user_id: 8, created_at: "2016-07-02 07:44:56", updated_at: "2016-07-02 07:44:56">]>

Ctrl + D で終了する。
※ なお、user.rb で設定していないと例外が発生する。

2.3.0 :002 > second_user.microposts
NoMethodError: undefined method `microposts' for #<User:0x007faa00082788>
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activemodel-4.2.2/lib/active_model/attribute_methods.rb:433:in `method_missing'
        from (irb):2
        from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.2/lib/rails/commands/console.rb:110:in `start'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.2/lib/rails/commands/console.rb:9:in `start'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.2/lib/rails/commands/commands_tasks.rb:68:in `console'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.2/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.2/lib/rails/commands.rb:17:in `<top (required)>'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.2/lib/active_support/dependencies.rb:274:in `require'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.2/lib/active_support/dependencies.rb:274:in `block in require'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.2/lib/active_support/dependencies.rb:240:in `load_dependency'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.2/lib/active_support/dependencies.rb:274:in `require'
        from /home/ubuntu/workspace/toy_app/bin/rails:9:in `<top (required)>'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.2/lib/active_support/dependencies.rb:268:in `load'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.2/lib/active_support/dependencies.rb:268:in `block in load'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.2/lib/active_support/dependencies.rb:240:in `load_dependency'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.2/lib/active_support/dependencies.rb:268:in `load'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/commands/rails.rb:6:in `call'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/command_wrapper.rb:38:in `call'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/application.rb:180:in `block in serve'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/application.rb:153:in `fork'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/application.rb:153:in `serve'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/application.rb:128:in `block in run'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/application.rb:122:in `loop'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/application.rb:122:in `run'
        from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-1.1.3/lib/spring/application/boot.rb:18:in `<top (required)>'
        from /usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from /usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from -e:1:in `<main>'2.3.0 :003 > 

継承階層

作成したモデル(Users, Microposts) は ActionController::Base を継承する。
このため、作成したモデルはデータベースにアクセスしカラムをあたかもRubyの属性のように扱える。
また、作成したモデルコントローラ(UsersController, MicropostController) は ApplicationController を継承する。
このため、ApplicationControllerで定義したルールはすべてのコントローラに反映される。

デプロイ

ローカルに変更をコミットし、bitbucket に push する

$ git status
$ git add -A
$ git commit -m "Finish toy app"
$ git push

herokuにデプロイ。

$ git push heroku    # デプロイ
$ heroku run rake db:migrate   # マイグレーション