ドットインストール「Ruby on Rails 4入門」メモ

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

01 Ruby on Railsとはなにか?

  • 概要
    • webアプリケーションフレームワーク
  • 公式サイト -http://rubyonrails.org/
  • DEMO
    • todoアプリ
  • 知識
    • Ruby
    • HTML/CSS/JavaScript/jQuery
    • sqlite/activerecord
  • 環境
    • localhost

02 DRY/CoC/MVCアーキテクチャとは?

  • 哲学
    DRY(Don't Repeat Yourself)
    CoC(Convention over Configuration:設定よりも規約)

  • MVCアーキテクチャ
    Model:データ
    View:画面
    Controller:ModelとViewを取り持つもの

03 はじめてのRuby on Rails

アプリケーションの作成

rails new myapp

アプリケーションフォルダに移動

cd myapp/

サーバー起動

rails s

エラーが出た時にはgemfileのrubyレーサーをonにする

vi Gemfile
# gem 'therubyracer', platforms: ruby

のコメントを外す

bundleをインストール

bundle install

サーバー起動

rails s

ブラウザからサーバーが立ち上がっているか確認

localhost:3000

主にいじるのは下記3つのフォルダ
・app
・config
・db

04 Scaffoldを使ってみよう

Scaffoldとはシンプルなアプリケーションを簡単につくるための仕組み。

controll+Cでサーバーストップ

ユーザー管理のアプリケーションを作成する場合

rails generate scaffold User name:string score:integer

このコマンドによって作られたファイルの中に、
db/migrate/yyyymmddhhmmss_create_users.rb
というのがあるがこれはこの設定でdbをうまいこと操作してよというファイルができていてこれをマイグレーションファイルという。

これをDBに反映させる

rake db:migrate

サーバー起動

rails s

ブラウザで確認

localhost:3000/users

ユーザーの管理画面が自動で生成されている。

シンプルでないアプリケーションを作りたいときには、ゼロから作っていく必要がある。

05 タスク管理アプリを作ってみよう

最初にサーバー落としてmyappから脱出

control+C
cd ..

アプリ名:TaskApp

Projectが登録できてその下にTaskを作ることができて完了などの管理ができるようにする。

bundleをスキップしてtaskapp作成

rails new taskapp --skip-bundle

taskappの中に移動

cd taskapp

gemfileの編集

vi Gemfile

「# gem 'therubyracer', platform: :ruby」の#を削除してコメントアウトを外す

保存して終了

esc => :wq

サーバー立ち上げ

rails s

ブラウザから確認

localhost:3000

サーバー停止

control+C

modelを作成

Projectというmodelを文字列のタイトルで生成する(属性のデフォルトはstringだからstringはいらなかったりする。)

rails g model Project title:string #gはgenerateの略

※ modelを生成するときに注意しなくてはいけないのは、「単数形」かつ「最初は大文字」でなくてはならない。

ということ。これを守らないとエラーが返って来る。

で上記コマンドを実行するとマイグレーションファイルが生成される。

dbに反映

rake db:migrate

06 rails db/rails consoleを使おう

modelがちゃんとできたか確認する。DBにアクセス

rails db

テーブルを確認

.schema

sqliteから出る

.exit

ここで作ったmodelをインタラクティブにrubyをいじりながら作る

rails console

オブジェクト作成

p = Project.new(title: "p1")
p.save

確認

p

オブジェクト作成

Project.create(title: "p2")

確認

Project.all

DBに入る

rails db

確認

select * from projects;

07 Controllerを作ってみよう

controllerをつくる

rails g controller Projects

※controllerを作りたいときには、必ず複数形にすることは忘れずに。

finderで「taskapp>app>controller」を見ると、projects_controller.rbができているのがわかるので、この中にいろいろと処理を書いていく。

まずは「taskapp>config」の中にroutes.rbがあるので、それを開いて
「resources :products」というのがあるので、それを2行目にコピペして、productsをprojectsに書き換える。
これによって、プロジェクトに関するルーティングを自動生成してくれるようにする。

routingの確認

rake routes

これによって出てくる情報が重要だったりする。

Prefix Verb URI Pattern Controller#Action
projects GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project GET /projects/new(.:format) projects#new
edit_project GET /projects/:id/edit(.:format) projects#edit
project GET /projects/:id(.:format) projects#show
PATCH /projects/:id(.:format) projects#update
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy

08 Projectsの一覧を表示させよう

Project/controller内の「projects_controller.rb」を開いてindexactionを作成する。

class ProjectsController < ApplicationController
    def index
        @projects = Project.all #viewの中でそのまま使える
    end
end

viewの中にindexファイルを作成
views/projectsの中に「index.html.erb」を作成する。
ファイル名はprojects_controller.rbのindexに自動で対応するために上記のような書き方にする。

erbファイルの中でループを回す場合、<% %>で囲ってあげる。
似たもので<%= %>という記法があるが、次に書いた式を評価してその内容を表示しなさいという内容。

index.html.erbに書く内容は以下。

<h1>Projects</h1>
<u1>
    <% @projects.each do |project| %>
    <li><%= project.title %></li>
    <% end %>
</u1>

サーバー立ち上げ

rails s

ブラウザから確認

localhost:3000/projects

09 rootの設定をしよう

毎回localhost:3000/projectsにアクセスするのはめんどくさいので、localhost:3000/projectsに表示される内容をlocalhost:3000にアクセスするだけで表示されるようにしよう。

それをやるためには、configフォルダ内の「routes.rb」をいじる。

リソースの下に以下を記述
root 'projects#index'
※projectsはサブフォルダ、indexはおそらくprojects_controller内のindex関数のことか?

10 共通テンプレートを編集しよう

viewにはこれしか書かれていないのにHTMLソースにはヘッダーとかが書かれている。
これはviewの中のlayoutフォルダの中のファイル「application.html.erb」に入っている。

この中に共通のheaderとかfooterとか書かれていて、viewの中のファイルに書いた内容は
<%= yield %>に反映される。

全ページ共通でロゴ画像を表示しよう

画像を表示するのにはimage_tag helperを使うと便利。

「application.html.erb」の中のyieldの行前に以下のように記述。

<%= image_tag "logo.png" %>

logo.pngを「app/assets/images」にロゴ画像を保存。

stylesheet内のファイル「application.css」に以下の記述をすると背景色を変えることができる。

body { background: #eee;}

homeのリンクを作成する。ファイル「application.html.erb」内のyieldの次の行に以下の内容を記入する。

11 Projectsの詳細を表示しよう

プロジェクト名を押したらそのプロジェクトの詳細に飛ぶようにする。

viewの中のファイル「index.html.erb」を下記のように編集

<h1>Projects</h1>
<u1>
    <% @projects.each do |project| %>
    <li><%= link_to project.title, project_path(project.id) %></li>
    <% end %>
</u1>

actionを決める。controller内のファイル「projects_controller.rb」を編集
projectのshowを作らなくてはいけないので以下のような記述をする。

class ProjectsController < ApplicationController
    def index
        @projects = Project.all #viewの中でそのまま使える
    end
    def show
        @Project = Project.find(params[:id]) #URLで渡ってきた数字はparamsで取ってこれる。シンボルはroutesに書かれているid。
    end
end

indexを作成した時と同じようにshow.html.erbも作成する。記述する内容としては以下のとおり。

<h1><%= @project.title %></h1>

ブラウザで確認すると、projectタイトルをクリックすると次のページに遷移するようになっている。

12 新規作成フォームを作ろう

プロジェクトを追加するというページを作成する。
project.newというのを作って、そこにフォームを設置してその内容をpostで受け取ってデータベースに保存する。

index.html.erbの最後に以下の内容を記述

<p><%= link_to "Add New", new_project_path %></p>

project_controller.rbのクラスに以下のメソッドを追加

    def new
        @project = Project.new
    end

viewのprojectsフォルダに「new.html.erb」を追加

<h1>Add New</h1>
<%= form_for @project do |f| %>
<p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
</p>
<p>
    <%= f.submit %>
</p>
<% end %>

13 データを保存してみよう

フォームが作れたのでpostを作ってデータを保存する。project_controller.rbのクラスの中に以下のメソッドを記述。

    def create
        @project = Project.new(project_params)
        @project.save
        redirect_to projects_path
    end
    private
        def project_params #project_paramsについてはprivate関数で定義するのが代表的な手法           params[:project].permit[:title] #projectで渡ってきた中の物のうち、タイトルだけを引っ張ってきてねという意味。セキュリティ上、フォームから渡ってきたものについてプロジェクトとタイトルだけ必要という時はこういうふうにフィルタリングをかけるのが最近のやり方。
        end

14 Validationを設定しよう

今の段階では何も入れなくても追加できるような状況なのでバリデーションを使って、ある条件の時は保存しないようにしよう。

modelの中でバリデーションを定義。今回は空の場合は保存できないようにする。project.rbのクラスに以下のような記述。

validates :title, presence: true

これで空の場合は保存できないようになる。

ここでエラーが出た場合は、Add Newのままにするようにする。projects_controller.rbのcreateメソッドを以下に修正。

    def create
        @project = Project.new(project_params)
        if @project.save
            redirect_to projects_path
        else
            render 'new' #newのviewに戻る
        end
    end

15 エラーメッセージを表示しよう

バリデーションエラーを表示する。new.html.erbを編集してまずはエラーメッセージを表示する。

<h1>Add New</h1>
<%= form_for @project do |f| %>
<p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
    <% if @project.errors.any? %> <%# project.errorsにエラーがあるかどうかで条件分岐 %>
    <%= @project.errors.inspect %>
    <% end %>
</p>
<p>
    <%= f.submit %>
</p>
<% end %>

エラーを確認すると@messages={:title=>[""can't be blank]}と出てくるので、new.html.erbのinspectの部分を以下のように再編集。

messages[:title][0]

自分でメッセージを変えたいときにはproject.rbに以下のような記述。

class Project < ActiveRecord::Base
    validates :title, presence: {message: "入力してください"}
end

バリデーションルールはいくらでも変えられる。長さを3文字以上にしたい場合。

class Project < ActiveRecord::Base
    validates :title,
    presence: {message: "入力してください"},
    length: {minimum: 3, message: "短すぎ!"}
end

16 編集フォームを作ろう

編集に関するルーティング

編集はeditにある
更新はupdateにある。
index.html.erbを編集。
liタグの中に以下の内容を追加。

<%= link_to "[edit]", edit_project_path(project.id) %>

そうするとプロジェクト名の横にeditボタンができる。

actionを追加。project_controller.rbのクラスに以下のメソッドを追加。

    def edit
        @project = Project.find(params[:id])
    end

フォームを作る。view/projectsの中にedit.html.erbを作成。new.html.erbのh1タグのタイトルだけ変えればOK。

<h1>Edit</h1>
<%= form_for @project do |f| %>
<p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
    <% if @project.errors.any? %> <%# project.errorsにエラーがあるかどうかで条件分岐 %>
    <%= @project.errors.messages[:title][0] %> <%# :titleをキーにして配列の0番目を表示 %>
    <% end %>
</p>
<p>
    <%= f.submit %>
</p>
<% end %>

17 データを更新しよう

projects_controller.rbの中に以下のメソッドを追加

    def update
        @project = Project.find(params[:id])
        if @project.update(project_params)
            redirect_to projects_path
        else
            render 'edit'
        end
    end

newとフォームが全く同じなので共通化する。
edit.html.erbのh1タグ以外をカットして以下の内容を記述

<%= render 'form' %>

view/projectsの中に「_form.html.erb」を作成。先ほどカットした内容をペースト

<%= form_for @project do |f| %>
<p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
    <% if @project.errors.any? %> <%# project.errorsにエラーがあるかどうかで条件分岐 %>
    <%= @project.errors.messages[:title][0] %> <%# :titleをキーにして配列の0番目を表示 %>
    <% end %>
</p>
<p>
    <%= f.submit %>
</p>
<% end %>

new.html.erbもeditと同じように書き換え。

<h1>Add New</h1>
<%= render 'form' %>

18 データを削除しよう

アクションで言うとdeleteなのでdestroyを使っていく。
viewの中のindex.html.erbの中にliタグ内に以下の内容を記述。

<%= link_to "[Delete]", project_path(project.id), method: delete, data: { confirm: "are you sure?" } %>

destroyアクションを作っていく。projects_controller.rbに以下のメソッドを記述。

    def destroy
        @project = Project.find(params[:id])
        @project.destroy
        redirect_to projects_path
    end

19 before_actionを使ってみよう

controllerに重複したコードがあるのでそれをなくしていく。DRYの哲学を実践。

@project = Project.find(params[:id])

がたくさん出てきているのでそれらの重複をすっきりさせる。
まとめて定義するためにbofore_actionを使う。
projects_controller.rbのクラス内の一番最初にbefore_actionを定義する。

before_action :set_project, only: [:show, :edit, :update, :destroy]

set_projectの関数を作る。他から特に参照されることはないので、privateの中に書けばOK。

        def set_project
            @project = Project.find(params[:id])
        end

他のメソッド内の@project = Project.find(params[:id])を削除すれば、すっきりしたコードになる。

また、after_actionというのもあるので興味がある人はggrks。

20 Tasksの設定をしていこう

プロジェクトの詳細画面にタスクを追加して、一覧して、削除するということをやる。

サーバ停止

control+C

ターミナルから以下のコマンド

rails g model Task title done:boolean project:references

意味は「titleが文字列型、doneが真偽値型、projectと紐付いている、Taskというmodelを作成せよ」

作成されたmodelというかtaskについてのmigrationfileをいじる。boolean :doneのところを未完了(false)にしておく。

t.boolean :done, default: false

次にターミナルからrake db:migrateを実行してDBを設定する。

同じくターミナルからtaskのcontrollerを作成

rails g controller Tasks

21 Associationの設定をしよう

modelの関連付けをする。
taskのmodel(task.rb)についてはターミナルからproject:referencesをやったので自動でやってくれたが、projectのmodelについては自動でやってくれないので手動で関連付ける必要がある。
project.rbを開いて以下の内容を記述。

has_many :tasks

これでproject1に対してtaskNの関連付けをすることができる。

次にルーティングの設定。
routes.rbを以下のように編集。

resources :projects do
    resources :tasks, only: [:create, :destroy]
  end

ちゃんとできたかどうかターミナルから確認

rake routes

22 Tasksの新規作成フォームを作ろう

サーバー起動

rails s

プロジェクト詳細の下にタスクが表示されるようにする。show.html.erbを編集

<h1><%= @project.title %></h1>
<u1>
<% @project.tasks.each do |task| %>
<li><%= task.title %></li>
<% end %>
<li>
    <%= form_for [@project, @project.tasks.build] do |f| %>
    <%= f.text_field :title %>
    <%= f.submit %>
    <% end %>
</li>
</u1>

23 Tasksを保存していこう

create actionを作っていく
tasks_controller.rbを編集

class TasksController < ApplicationController
    def create
        @project = Project.find(params[:project_id])
        @task = @project.tasks.create(task_params)
        redirect_to project_path(@project.id)
    end
    private
        def task_params
        params[:task].permit(:title)
        end
end

今の状態だと何も入れなくてもタスクとして入ってしまうのでバリデーションをかける。
tasks.rbを以下のように編集

class Task < ActiveRecord::Base
  belongs_to :project
  validates :title, presence: true
end

24 Tasksの削除をしてみよう

index.html.erbの中のdeleteの部分をコピーして、viewの中のshow.html.erbを編集。

<h1><%= @project.title %></h1>
<u1>
<% @project.tasks.each do |task| %>
<li>
    <%= task.title %>
    <%= link_to "[Delete]", project_task_path(task.project_id, task.id), method: :delete, data: { confirm: "are you sure?" } %>
</li>
<% end %>
<li>
    <%= form_for [@project, @project.tasks.build] do |f| %>
    <%= f.text_field :title %>
    <%= f.submit %>
    <% end %>
</li>
</u1>

deleteをおした時のアクションを設定。tasks_controller.rbにdestroyメソッドを追加。

    def destroy
        @task = Task.find(params[:id])
        @task.destroy
        redirect_to project_path(params[:project_id])
    end

25 check_box_tagを使おう

タスクの前にチェックボックスを作る。show.index.erbのタスクタイトルタグの前に以下の文を追加。

<%= check_box_tag '', '', task.done, {'data-id' => task.id, 'data-project_id' => task.project_id} %>

26 toggleアクションを作ろう

チェックボックスをクリックした時postが飛ぶようにしたい。

show.html.erbの最後に以下のスクリプトを作成。

<script>
    $(function(){
        $("input[type=checkbox]").click(function(){
            $.post('/projects/'+$(this).data('project_id')+'/tasks/'+$(this).data('id')+'/toggle');
        });
    })
</script>

こちらのパスに命令を投げるがルーティングが設定されていないのでconfigの中のroutes.rbに以下の内容を追記。

post '/projects/:project_id/tasks/:id/toggle' => 'tasks#toggle'

tasks_controller.rbにtoggleメソッドを作成。

    def toggle
        @task = Task.find(params[:id])
        @task.done = !@task.done
        @task.save
    end

サーバー停止してrake routesで確認

togglが作成されているのを確認できればOK。次回で動作確認。

27 Tasksの状況を切り替えよう

サーバを起動して挙動を確かめてみる。
要素を確認してみるとテンプレートがないと怒られる。今回はテンプレートを使わないが、テンプレートを使わないという記述をする必要がある。task_controller.rbでテンプレートを使わないということをtoggleメソッド内の最初に以下の記述。

render nothing: true

28 Tasksの数を表示させよう

プロジェクト一覧のところにすべてのタスク数と残タスクの数を表示させる。
まず全タスク数を表示。inde.html.erbのtitleを以下のように編集。

<%= link_to project.title, project_path(project.id) %> (<%= project.tasks.count %>)

次に残タスク数の表示。tasks.rbに以下の記述。
scope :unfinished, -> {where(done: false)} #doneがfalseのものを検索条件として保存しなさいという意味。

次にindex.html.erbを以下のように編集。

<%= link_to project.title, project_path(project.id) %> (<%= project.tasks.unfinished.count %>/<%= project.tasks.count %>)

参考サイト、外部サイトなど

Ruby on Rails 4入門 (全28回) - プログラミングならドットインストール
keisukeohta/dotinstall-rails-taskapp - github
link_toメソッドを使ったリンクの作成
使用するアクションへのルーティングだけを設定