LoginSignup
1
1

More than 5 years have passed since last update.

MyFirstRails #4 TODOアプリを作ってみよう!

Posted at

MyFirstRails #4 TODOアプリを作ってみよう!

概要

Railsにこれから初めて触れる方を対象にしたチュートリアルです
簡単なTODOアプリを作成するチュートリアルになります

実際に作成したものはこちら

チュートリアル

Railsのひな型を作る

まず、rails newを実行し、Railsアプリのひな型を作成します。

rails new todo

次に、作成したRailsアプリのディレクトリへと移動します。

cd todo

ScaffoldでCRUDを作成

rails g scaffold コマンドを使い、ブログに必要な一覧ページや記事作成ページなどを作ります

rails g scaffold task title:string content:text date:date

その後、rails db:migrateでマイグレーションを行います

rails db:migrate

あとはrails sを実行して、localhost:3000/tasksにアクセスします

Trixでリッチなテキストエディターを使う

trixGemfileに追加します

Gemfile
gem 'trix'

その後、bundle install を実行します

bundle install

bundle installした後、app/assets/javascripts/application.js//= require trixを追加します

app/assets/javascripts/application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
// vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require rails-ujs
//= require activestorage
//= require trix
//= require turbolinks
//= require_tree .

次に、app/assets/javascripts/application.cssapp/assets/javascripts/application.scssにリネームして以下のように変更します

app/assets/javascripts/application.scss
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */
 @import "trix";

@import "trix"; を追加しただけですね

最後に、app/views/tasks/_form.html.erbapp/views/tasks/show.html.erbを以下のように変更します。

app/views/tasks/_form.html.erb
<%= form_with(model: task, local: true) do |form| %>
  <% if task.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(task.errors.count, "error") %> prohibited this task from being saved:</h2>

      <ul>
      <% task.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>

  <div class="field">
    <%= form.label :content %>
    <%= form.hidden_field :content, id: :content_text %>
    <trix-editor input="content_text"></trix-editor>
  </div>

  <div class="field">
    <%= form.label :date %>
    <%= form.date_select :date %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>
app/views/tasks/index.html.erb
<p id="notice"><%= notice %></p>

<h1>Tasks</h1>

<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Content</th>
      <th>Date</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @tasks.each do |task| %>
      <tr>
        <td><%= task.title %></td>
        <td><%= sanitize task.content, tags: %w(h1 h2 h3 h4 h5 h6 ul ol li p a img table tr td em br strong div), attributes:  %w(id class href) %></td>
        <td><%= task.date %></td>
        <td><%= link_to 'Show', task %></td>
        <td><%= link_to 'Edit', edit_task_path(task) %></td>
        <td><%= link_to 'Destroy', task, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Task', new_task_path %>
app/views/tasks/show.html.erb
<p id="notice"><%= notice %></p>

<p>
  <strong>Title:</strong>
  <%= @task.title %>
</p>

<p>
  <strong>Content:</strong>
  <%= sanitize @task.content, tags: %w(h1 h2 h3 h4 h5 h6 ul ol li p a img table tr td em br strong div), attributes:  %w(id class href) %>
</p>
</p>

<p>
  <strong>Date:</strong>
  <%= @task.date %>
</p>

<%= link_to 'Edit', edit_task_path(@task) %> |
<%= link_to 'Back', tasks_path %>

これで、リッチなテキストエディタが使用できるようになります。

カテゴリー機能の実装

TODOアプリですので「緊急」などのカテゴリーを登録して判断できるようにしたいと思います

まずは、カテゴリー用のCRUDのひな型をrails g scaffoldで作成します

rails g scaffold category name:string

scaffoldした後は、いつものようにrails db:migrateを実行します

rails db:migrate

localhost:3000/categoriesにブラウザからアクセスするとカテゴリーを新規に作成したり、カテゴリー名を編集することができるようになっているはずです!

次に、作成しているTaskcategoryのカラムを追加します

rails g migration AddCategoryToTask category:string

再び、rails db:migrateを実行します

rails db:migrate

あとは、コントローラーとビューでcategoryをパラメータとして受け取れるように修正します。

app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  before_action :set_task, only: [:show, :edit, :update, :destroy]
  before_action :set_category, only: [:new, :edit]

  # GET /tasks
  # GET /tasks.json
  def index
    @tasks = Task.all
  end

  # GET /tasks/1
  # GET /tasks/1.json
  def show
  end

  # GET /tasks/new
  def new
    @task = Task.new
  end

  # GET /tasks/1/edit
  def edit
  end

  # POST /tasks
  # POST /tasks.json
  def create
    @task = Task.new(task_params)

    respond_to do |format|
      if @task.save
        format.html { redirect_to @task, notice: 'Task was successfully created.' }
        format.json { render :show, status: :created, location: @task }
      else
        format.html { render :new }
        format.json { render json: @task.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /tasks/1
  # PATCH/PUT /tasks/1.json
  def update
    respond_to do |format|
      if @task.update(task_params)
        format.html { redirect_to @task, notice: 'Task was successfully updated.' }
        format.json { render :show, status: :ok, location: @task }
      else
        format.html { render :edit }
        format.json { render json: @task.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /tasks/1
  # DELETE /tasks/1.json
  def destroy
    @task.destroy
    respond_to do |format|
      format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_task
      @task = Task.find(params[:id])
    end

    def set_category
      @categories = Category.all
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def task_params
      params.require(:task).permit(:title, :content, :date, :category)
    end
end
app/views/tasks_form.html.erb
<%= form_with(model: task, local: true) do |form| %>
  <% if task.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(task.errors.count, "error") %> prohibited this task from being saved:</h2>

      <ul>
      <% task.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>

  <div class="field">
    <%= form.label :category %>
    <%= form.collection_select(:category, @categories, :name, :name, include_blank: true) %>
  </div>

  <div class="field">
    <%= form.label :content %>
    <%= form.hidden_field :content, id: :content_text %>
    <trix-editor input="content_text"></trix-editor>
  </div>

  <div class="field">
    <%= form.label :date %>
    <%= form.date_select :date %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

これで、作成したカテゴリー名をTODOのカテゴリー名に使用できるようになりました!

root_pathの追加

config/routes.rbを編集して、root_pathを使用できるようにします

config/routes.rb
Rails.application.routes.draw do
  root 'tasks#index'
  resources :categories
  resources :tasks
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

Bootstrap4の適用

このままではデザインなどが簡素すぎるのでBootstrapを使いたいと思います。

まず、Gemfilegem 'bootstrap', '~> 4.2.1'gem 'jquery-rails'を追加し、bundle installします。

Gemfile
gem 'bootstrap', '~> 4.2.1'
gem 'jquery-rails'
bundle install

もし、gemの依存関係でうまくいかない場合は、bundle updateを実行してからbundle installを実行してください

bundle update
bundle install

また、Windowsのローカル環境でアプリを作成している場合は、SQLite3がバージョンアップしてしまいます
以下のようにバージョンを固定してからbundle updatebundle installを実行して下さい

Gemfile
gem 'sqlite3', '1.3.13'
bundle update
bundle install

その後、app/assets/javascripts/application.jsapp/assets/stylesheets/application.scssを下記のように変更します

app/assets/javascripts/application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
// vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require rails-ujs
//= require activestorage
//= require trix
//= require jquery3
//= require popper
//= require bootstrap-sprockets
//= require turbolinks
//= require_tree .
app/assets/stylesheets/application.scss
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */
 @import "trix";
 @import "bootstrap";

その後、config/boot.rbを以下のように修正します

config/boot.rb
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)

ENV['EXECJS_RUNTIME'] = 'Node'

require 'bundler/setup' # Set up gems listed in the Gemfile.
require 'bootsnap/setup' # Speed up boot time by caching expensive operations.

これでBootstrapが使用できるようになりました。

最後に、app/views/layouts/_header.html.erbを作成し、app/views/layouts/application.html.erbでパーシャルとして呼び出します。

app/views/layouts/_header.html.erb
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <%= link_to "ToDo", root_path, class: "navbar-brand" %>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="dropdown">
    <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
      Menu
    </button>
    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
      <%= link_to 'Tasks', tasks_path, class: "dropdown-item" %>
      <%= link_to 'Categories', categories_path, class: "dropdown-item" %>
    </div>
  </div>
</nav>
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>TODO Tutorial</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= render 'layouts/header'%>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>

rails sでサーバを起動し、ナビゲーションバーが表示されていればOKです。

カテゴリ検索機能を実装

select2-railsを使い、プルダウン内で検索ができるようにします!

Gemfilegem 'select2-rails'と追加し、bundle installを実行します

Gemfile
gem 'select2-rails'
bundle install

次に、app/assets/javascripts/application.jsapp/assets/stylesheets/application.scssを修正します

app/assets/javascripts/application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
// vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require rails-ujs
//= require activestorage
//= require trix
//= require jquery3
//= require popper
//= require bootstrap-sprockets
//= require select2
//= require turbolinks
//= require_tree .

 $(document).ready(function() {
     $('select#task_category').select2();
  });
app/assets/stylesheets/application.scss
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */
 @import "trix";
 @import "bootstrap";
 @import "select2";
 @import "select2-bootstrap";

これで、localhost:3000/tasks/newでカテゴリを登録する際にプルダウン検索が使用できるようになりました!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1