初めてのRuby on Rails。Twitterみたいなサイトを作成しよう

  • 38
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

1 Railsとは

  • Webアプリケーションを開発するために設計されたものをWebアプリフレームワークと言います。
  • フレームワーク自体はプログラミング言語ではありません。フレームワークはある特定のことに特化した機能を集めたものです。
  • 最も先進的で安定しており、豊富なRubyGemsライブラリがあることで他のフレームワークに比べプロトタイプを作るスピードを早めることが可能

2 Railsの導入

  • RubyGemsを使ってインストール。
sudo gem install rails
  • Xcodeまたはコマンドラインツールに問題がある場合は、下記コマンドで再インストールする。
xcode-select --install

3 Railsアプリの新規作成

  • Twitterのようなアプリを soushi-twitter という名前作ることにします。
  • 下記コマンドを打つと、自動でRailsアプリのテンプレートが生成されます。
rails new soushi-twitter
cd ~/soushi-twitter
  • treeコマンドで自動生成されたファイルを確認します。
tree ~/soushi-twitter
├── Gemfile
├── Gemfile.lock
├── README.rdoc
├── Rakefile
├── app
├── bin
├── config
├── config.ru
├── db
├── lib
├── log
├── public
├── test
├── tmp
└── vendor

4 Railsアプリをカスタマイズする

4.1 モデルー・ビュー・コントローラ(MVCモデル)

  • RailsにおけるモデルはPush-MVCと呼ばれるものです。
  • これは、ModelとView、両者を知っているのは、Controllerしかいません。よってControllerにがんばってもらおう、という戦略です。
  • ViewはControllerがトリガになって更新されるため、受け身です。このことから、このViewのことをPassive Viewと呼んだりします。
  • 参考 MVC、本当にわかってますか?

4.2 ビューおよびコントローラーの作成

  • コマンド1つで作成できます。
  • このindexというのは、ユーザーの一覧ページ。showというのは、ユーザーのプロフィールページです。
  • indexやshowは自分で==自由に名前をつけることが可能==ですが、あとで説明するように==index==、==show==というようにつけるのが==良し==とされています。
  • また、==コントローラー名は==usersというように==複数形==にするのがよしとされています。
  • こういう暗黙の約束事のようなものをRailsの規約と言います。 Railsはその名の通りレールに沿って作ればカンタンに作れる、という意味なので、出来る限りRailsが敷いたレールの上を走りましょう。
rails g controller users index show
  • 次のようなファイルが自動生成されます。
app/controllers/users_controller.rb
app/views/users/index.html.erb
app/views/users/show.html.erb

4.3 サーバーの起動

  • 実は、ここまででもうWebページが完成しています。
rails s
  • rails sコマンドでサーバーを起動し、Webブラウザでhttp://0.0.0.0:3000/users/indexにアクセスしてみます。

初めてのRailsページ

4.4 ビューのカスタマイズ(1)

  • app/views/users/show.html.erbを次のように編集します。

  • app/views/users/show.html.erb

<h1>Soushi Yamamoto</h1>
<p>soushiy</p>
<ul>
    <li>Location : Tokyo</li>
    <li>About   : Hello</li>
</ul>

rails2.png

  • Webブラウザでhttp://0.0.0.0:3000/users/showにアクセスします。

rails3.png

4.5 ビューのカスタマイズ(2)

  • 再度、app/views/users/show.html.erbを次のように編集します。
  • app/views/users/show.html.erb
<h1><%= @user[:name] %></h1>
<p><%= @user[:username] %></p>
<ul>
    <li>Location : <%= @user[:location] %></li>
    <li>About   : <%= @user[:about] %></li>
</ul>
  • 再度、Webブラウザでhttp://0.0.0.0:3000/users/showにアクセスします。
  • エラーが発生しています。

rails4.png

  • undefined method '[]' for nil:NilClassというエラーは、@userから情報を引っ張ろうとしているけど、@userに情報が入っていないということで起こっています。
  • そこで、コントローラーで@userに情報を埋め込みます。

4.6 コントローラーのカスタマイズ

  • コントローラーを編集して、@userに情報を埋め込みます。
  • app/controllers/users_controller.rbを次のように変更します。
class UsersController < ApplicationController
    def index
    end

    def show
        @user = Hash.new
        @user[:name] = 'Soushi Yamamoto'
        @user[:username] = 'soushiy'
        @user[:location] = 'Tokyo, Japan'
        @user[:about] = 'Hello.'
    end
end
  • 正しく表示できました。

rails6.png

5 ルーチングの設定

5.1 ルーチングの必要性

  • http://0.0.0.0:3000/users/showにアクセスすると、すべて同じ人のプロフィールになっています。
  • これをhttp://0.0.0.0:3000/users/show/soushiyにアクセスすると、soushiyのプロフィールが表示され、
  • http://0.0.0.0:3000/users/show/tanaka にアクセスすると、tanakaのプロフィールがそれぞれ表示されるようにするために、ルーチングという仕組みを使います。 ### 5.2 ルーチングの役割
  • ルーチングはユーザーがアクセスしたURLをもとに何を表示するかをすべて振り分けています。
  • すなわち、ルーチングの役割は、ユーザーがSoushi Yamamotoを表示しろというURLにアクセスしたら、その情報を表示するようにし、Taro Tanakaを表示しろというURLにアクセスしたら、その情報を表示するようにする、いわば「URLの仕分け」のようなことをしています。
  • したがって、実はURLにアクセスした時に最初に通るところがルーチングになるのです。
  • ページが表示されるまでの流れは以下のとおり。
  1. ユーザーがURLにアクセス
  2. ルーチングが仕分け
  3. コントローラーが値を入れる
  4. ビューがコントローラーから渡された値を表示

5.3 ルーチングのカスタマイズ

  • http://0.0.0.0:3000/users/show/soushiyで、プロフィールページを表示したいので、config/routes.rbを下記のように編集します。

  • config/routes.rb

Rails.application.routes.draw do
  get 'users/index'
  get 'users/show'
  get 'users/show/:username' => 'users#show'
end
  • WEBブラウザでhttp://0.0.0.0:3000/users/show/soushiyにアクセスします。

rails7.png

6 ルーチングからコントローラーへ値を渡す

  • ルーチングの値はparams[:username]で取得可能。
  • これは、先ほど、ルーチングのファイルconfig/routes.rbget "users/show/:username" => "users#show"と記述したからである。

  • コントローラーの動作を、ルーチングによって変更するようにします。

  • app/controllers/users_controller.rbを下記のように変更します。

class UsersController < ApplicationController
    def index
    end

    def show
        @user = Hash.new
        if params[:username] == 'soushiy'
            @user[:name] = 'Soushi Yamamoto'
            @user[:username] = 'soushiy'
            @user[:location] = 'Tokyo, Japan'
            @user[:about] = 'Hello.'
        elsif params[:username] == 'tarot'
            @user[:name] = 'Taro Tanaka'
            @user[:username] = 'tarot'
            @user[:location] = 'Yamaguchi, Japan'
            @user[:about] = 'I'm Taro.'
        end
    end
end
  • WEBブラウザでhttp://0.0.0.0:3000/users/show/soushiyhttp://0.0.0.0:3000/users/show/tarotを開きます。

rails7.png

rails8.png

7. モデルの作成

  • Railsにおけるモデルとは、mysqlやHBase(大規模キーバリューストア)等を指す。
  • スキーマを直接定義するのではなく、マイグレーションを書く。

7.3.1 データベースの新規作成

  • db/development.sqlite3 が作成されます。
  • この時点では何もないまっさらなもの(スキーマやマイグレーションファイルも無い)。
rake db:create

7.3.2 モデルの作成

  • モデルはusersではなく、userという単数形であることに注意しましょう。これもRailsの敷いたレールの一つです。
カラム名 意味
name string 表示名
username string ユーザー名
location string 居住地
about text 自己紹介
rails g model user name:string username:string location:string about:text
  • 下記は、マイグレーションの型とMySQL、Rubyの型の対応表です。
マイグレーションの型 MySQLの型 Rubyの型
integer int(11) Fixnum
decimal decimal(10,0) BigDecimal
float float Float
string varchar(255) String
text text String
binary blob String
date date Date
datetime datetime Time
timestamp datetime Time
time time Time
boolean tinyint(1) TrueClass/FalseClass
  • 次のようなファイルが生成されます。
  • user.rb・・・モデルファイル
  • {日付}_create_users.rb・・・マイグレーションファイル
app/models/user.rb
db/migrate/20150825110207_create_users.rb
cat db/migrate/20150825110207_create_users.rb 
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :username
      t.string :location
      t.text :about

      t.timestamps null: false
    end
  end
end

7.3.3 マイグレーションファイルを用いてデータベースにスキーマを適用

  • 下記コマンドで、実際にスキーマが適用されたデータベースとなります。
rake db:migrate

8 データベースにデータを入れる

  • ==初期データを入れるためのファイル==db/seeds.rbを、下記のように変更します。
@user = User.new
@user.name = 'Soushi Yamamoto'
@user.username = 'soushiy'
@user.location = 'Tokyo, Japan'
@user.about = 'Hello, I am Soushi.'
@user.save

@user = User.new
@user.name = 'Taro Tanaka'
@user.username = 'tarot'
@user.location = 'Yamaguchi, Japan'
@user.about = 'Hi. I am Taro.'
@user.save
  • 次のコマンドでデータベースにデータを追加します。
rake db:seed

9 データベースのデータを表示する

  • コントローラーapp/controllers/users_controller.rbを次のように変更します。
  • 今回はUser.find_by(:username => params[:username])となっていますが、User.find_by(:name => 'Soushi Yamamoto')や、User.find_by(:id => 1)という検索も可能です。
  • idで探す場合は、単純にUser.find(1)として、idが1のユーザーを取得することもできます。
class UsersController < ApplicationController
    def index
    end

    def show
        @user = User.find_by(:username => params[:username])
    end
end
  • WEBブラウザでそれぞれのページにアクセスします。

rails9.png

rails10.png

10 ツイートを保存するためのビュー・コントローラー・モデルを作成する

  • ビューとコントローラーの作成
URL 意味
index タイムラインを表示する
show
new 新しいツイートを入力する画面
rails g controller tweets index show new
  • モデルの作成
カラム名 意味
title string タイトル
content text 内容
rails g model tweet title:string content:text
rake db:migrate

11 ツイートを入力するためのフォームを作る

  • 現在、http://0.0.0.0:3000/tweets/newの画面は、次のようになっています。

rails11.png

11.1 ビューを修正する

  • 新規ツイートを作成するための画面app/views/tweets/new.html.erbを、次のように変更します。
  • このようなものを==ヘルパー==と言います。 この例の場合は、フォームヘルパーと呼ばれるものです。
<%= form_for Tweet.new do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title %>
  <%= f.label :content %>
  <%= f.text_area :content %>
  <%= f.submit %>
<% end %>
  • views/tweetsフォルダが作成されています。

rails12.png

11.2 NoMethodError in Tweets#newエラーに対処する

  • ビューを修正した後、再度http://0.0.0.0:3000/tweets/newにアクセスすると、エラーが発生しています。

[uploading rails13.png...]()

  • エラー内容は、==フォームの送信先が存在しない==というものです。
undefined method `tweets_path' for #<#<Class:0x007fe02b2a1918>:0x007fe02b2f8308>
  • そこで、ルーチングの設定を書き換えて、送信先を定義してあげます。
  • config/routes.rbを次のように書き換えます。
  • ツイートのフォームを入力して、送信ボタンを押したら、tweetsコントローラーのcreate関数を呼びなさい、という意味です。==(create関数は未定義なので後で作成します。)==
Rails.application.routes.draw do
  get 'tweets/index'
  get 'tweets/show'
  get 'tweets/new'
  post 'tweets' => 'tweets#create'

  get 'users/index'
  get 'users/show/:username' => 'users#show'
end
  • 再度、http://0.0.0.0:3000/tweets/newにアクセスします。

rails13.png

  • ツイートを送信します。(失敗します。)

rails15.png

  • tweetsコントローラーに、create関数を追加します。
  • app/controllers/tweets_controller.rbを次のように変更します。
class TweetsController < ApplicationController
  def index
  end

  def show
  end

  def new
  end

  def create
  end
end
  • create関数は追加できましたが、何も処理していません。
  • 先ほどユーザー名の取得の際に、params[:username]としたのと同様に、params[:tweet][:title]でツイートのタイトルを取得します。

  • 以下の様な形で、パラメータが飛んできます。

params = { :tweet => { :title => "This is first tweet title", :content => "I am making how to make twitter app." } }
  • そこで、app/controllers/tweets_controller.rbを次のように変更します。
  • params[:tweet][:title]でタイトルの取得
  • params[:tweet][:content]で内容の取得
class TweetsController < ApplicationController
    def index
    end

    def show
    end

    def new
    end

    def create
        @tweet = Tweet.new
        @tweet.title = params[:tweet][:title]
        @tweet.content = params[:tweet][:content]
        @tweet.save
    end
end
  • ここまでで、ツイートの内容は正しく保存されるようになりました。しかし、再度ツイートボタンを押して投稿しようとすると、下記の画面になります。

rails16.png

  • これは、==create関数に対応するビューが存在しないため発生するエラーです。==
  • createのビューは必要ないので、もしもデータを保存し終わったらツイートの一覧にリダイレクトさせるようにしましょう。
  • app/controllers/tweets_controller.rbを次のように変更します。
class TweetsController < ApplicationController
    def index
    end

    def show
    end

    def new
    end

    def create
        @tweet = Tweet.new
        @tweet.title = params[:tweet][:title]
        @tweet.content = params[:tweet][:content]
        @tweet.save
        redirect_to '/tweets/index'
    end
end

12 ツイートの一覧表示

  • ツイートの一覧表示はtweets#indexを変更すればよいのでした。
  • 対応するコントローラーapp/controllers/tweets_controller.rbを次のように編集します。
  • @tweets = Tweet.allは、データベースからすべてのデータを取ってくるコマンドです。
class TweetsController < ApplicationController
    def index
        @tweets = Tweet.all
    end

    def show
    end

    def new
    end

    def create
        @tweet = Tweet.new
        @tweet.title = params[:tweet][:title]
        @tweet.content = params[:tweet][:content]
        @tweet.save
        redirect_to '/tweets/index'
    end
end
  • 次に、一覧表示のためのビューを変更します。
  • ここで、Rubyのforループのおさらいです。
  • 次のようにすると、0〜10までを足した数が表示されます。
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sum = 0
numbers.each do |number|
  sum += number
end

puts sum
  • このfor文を用いて、app/views/tweets/index.html.erbを次のように編集します。
  • <%<%=の違いに注意します。==イコールの無いものは、HTMLとして表示する必要のないもの==という意味です。
<% @tweets.each do |tweet| %>
  <h1><%= tweet.title %></h1>
  <p><%= tweet.content %></p>
<% end %>
  • 最後に、http://0.0.0.0:3000/tweets/indexにアクセスします。

rails17.png


この次のステップは?

ここまで学んできて、ある程度Railsの仕組みが理解できたでしょうか?
他にもまだまだやりたいことはたくさんあると思います。

画像をアップロードするためには、どうしたらいいの?
ユーザーのログインをして、ユーザーごとにツイートを表示したい。
実際のTwitterと連動して、ここでつぶやいたことをTwitterにも表示させたい。
などなど。

ここから先は、無限です。

Mitakalabコミュニティで学ぶもよし、本で独学するもよし、Google先生にきくもよし。

自分だけのアプリを作るべくがんばってください。

参考までに、この次のステップで有用なものを挙げておきます。

  • モデルを変更する

  • Railscasts : Railsの応用例がたくさん載っているサイトです。(英語・日本語)

  • Cumiki : Railsにかぎらず、Railsの応用例をどうやって付け加えるかを、レゴを組み立てるような手順で学ぶことができます。(日本語)

  • ドットインストール : Railsにかぎらず、基本的な点を動画を使ってわかりやすく解説されています。(日本語)

  • Ruby Toolbox : RailsにGemを追加して機能を付け加えたいときに、どんなGemがあるのかをカテゴリーごとに見ることができます。(英語)

参考文献