何度やってもRailsが身につかない。ドットインストールの講座をやったメモを備忘録として書く。

Ruby on Rails 4入門 (全28回) - プログラミングならドットインストール

コード

プロジェクト作成

$ rails new appname

  • --skip-bundle でバンドルのインストールを省略して高速化

サーバー起動

$ rails server または $ rails s

モデル作成

$ rails generate model Project title

  • モデル名は単数形、大文字始まり
  • メンバは、後ろに:string:integerをつけることで型を指定できる。省略するとstringとなる
  • rails g でも可

マイグレーションファイルが生成されるので、rake db:migrate DBへ反映させる

DB確認

$ rails db

sqlite> .schema
CREATE TABLE "projects" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar(255), "created_at" datetime, "updated_at" datetime);
CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL);
CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version");

コンソール

インタラクティブに操作できる。

$ rails console

  • p1 = Project.new("p1"); p1.save
  • p2 = Project.create("p2")

コントローラ作成

$ rails g controller Projects

  • コントローラの作成は複数形
  • app/controllers/projects_controller.rb が生成される

route 設定

作成したコントローラにブラウザからアクセスできるように、routeを設定する

# config/routes.rb
Rails.application.routes.draw do
  # 追加
  resources :projects

  ...
end

を追加する。

設定したルートの確認は rake routes でできる。

$ 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

共通テンプレート

<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
  <title>Taskapp</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>

<%= image_tag "logo.png" %> でイメージタグを埋め込む。画像ファイルは app/assets/images に置く。

<%= link_to "Home", projects_path %> でリンクの埋め込み。

モデルの詳細ページを作る

一覧のビューの中でリンクを指定する:

<!-- app/views/projects/index.html.erb -->
<%= link_to project.title, project_path(project.id) %>

コントローラにshowアクションを追加する:

# app/controllers/projects_controller.rb
  def show
    @project = Project.find(params[:id])
  end

ビューを追加する

<!-- app/views/projects/show.html.erb -->
<h1><%= @project.title %></h1>

アイテムの新規追加を作る

<!-- app/views/projects/index.html.erb -->
<%= link_to "Add New", new_project_path %>

アクションを追加:

# app/controllers/projects_controller.rb
  def new
    @project = Project.new
  end

ビューを追加

<!-- app/views/projects/new.html.erb -->
<%= form_for @project do |f| %>
<p>
  <%= f.label :title %><br>
  <%= f.text_field :title %>
</p>

<p>
  <%= f.submit %>
</p>

バリデーションの追加

入力が空の状態を防ぐなど、条件を付けられる

# app/models/project.rb
class Project < ActiveRecord::Base
  # 追加
  validates :title, presence: true
end

保存時、バリデーションに失敗したときに分岐させる

# app/controllers/projects_controller.rb
    if @project.save
      redirect_to project_path  # 成功した場合には一覧に飛ばす
    else
      render 'new'  # 失敗した場合にはもう一度新規追加画面に戻る
    end

要素の編集を追加

edit をコントローラ、ビューに追加して、編集画面を追加。

update で編集内容を保存。

編集画面を共通化する

newedit で表示しているフォームが全く同じ形なので、パーシャルを使って共通化する。

<!-- new.html.erb,edit.html.erb -->
  <%= render 'form' %>
<!-- app/views/projects/_form.html.erb -->
<%= form_for ... %>
  ...
<% end %>

要素の削除

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

コントローラにdestroy アクションを追加

# app/controllers/projects_controller.rb
  def destroy
    @project = Project.find(params[:id])
    @project.destroy
    redirect_to projects_path
  end

「タスク」モデルの追加

タスクという、プロジェクトと1対多となるモデルを作成

$ rails g model Task title done:boolean project:references

boolean で真偽値、referencesで他のモデルへの参照。

doneの初期値をfalseとするために、生成されたマイグレーションファイル(db/migrate/XXXX_create_tasks.rb)に default: false と指定してやる。

$ rake db:migrate でDBに反映

ProjectモデルにTaskへの指定を追加する

# app/models/project.rb
  has_many :tasks

ProjectがTaskと1対多であることを記述する

Taskの方は生成時に自動的に「belongs_to :project」という指定が入っているが Projectの方は自動的には追加されないので、してやる必要がある。

Taskへのルーティングを設定

# config/routes.rb
  resources :projects do
    # :projectsのアソシエーションとして指定、createとdestroyアクションのみ
    resources :tasks, only: [:create, :destroy]
  end
$ rake routes
       Prefix Verb   URI Pattern                               Controller#Action
project_tasks POST   /projects/:project_id/tasks(.:format)     tasks#create
 project_task DELETE /projects/:project_id/tasks/:id(.:format) tasks#destroy
...

タスクの新規追加

# app/controllers/tasks_controller.rb
  def create
    @project = Project.find(params[:project_id])
    @task = @project.tasks.create(task_params)
    redirect_to project_path(@project.id)
  end

  ...

チェックボックスの表示

<!-- app/views/projects/show.html.erb -->
    <%= check_box_tag '', '', task.done, {'data-id' => task.id, 'data-project_id' => task.project_id} %>
  • あとでpostメッセージを送る時に使えるように、データフィールドにID埋め込んでおく

toggleアクションを呼び出す

// app/views/projects/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'

アクションでは表示内容はないので、それを指定する

# app/controllers/tasks_controller.rb
  def toggle
    render nothing: true
    ...
  end