ブログアプリ⑨(タグのテーブルを作ろう)
タグのテーブルをつくる
$ rails g model tag tag:string Running via Spring preloader in process 27600 invoke active_record create db/migrate/20181206042331_create_tags.rb create app/models/tag.rb
記事とタグの中間テーブルをつくる
$ rails g model article_tag article:references tag:references Running via Spring preloader in process 34479 invoke active_record create db/migrate/20181206042916_create_article_tags.rb create app/models/article_tag.rb
そうそう。中間テーブルを作るときにreferences型を指定して作ったら、出来上がったモデルファイルに初めからアソシエーションが記述されてた。便利ー
articleモデルと今作ったtagモデルにもアソシエーションを設定したげる
models/article.rb class Article < ApplicationRecord has_many :article_tags has_many :tags, through: :article_tags end
models/tag.rb class Tag < ApplicationRecord has_many :article_tags has_many :articles, through: :article_tags end
マイグレートする
$ bundle exec rake db:migrate == 20181206042331 CreateTags: migrating ======================================= -- create_table(:tags) -> 0.0384s == 20181206042331 CreateTags: migrated (0.0386s) ============================== == 20181206042916 CreateArticleTags: migrating ================================ -- create_table(:article_tags) -> 0.0293s == 20181206042916 CreateArticleTags: migrated (0.0294s) =======================
これで必要なテーブルができた!
次はタグを新規につけられるようにするよ
ブログアプリ⑧(タグ機能を考えよう)
タグ機能をつける!
その前に。具体的に何をできるようにするか考える
- 記事を作成・編集するときにタグをつける
- 新規のタグを作る
- 既存のタグを使う
- 記事からタグを外す
- タグ一覧
- リストで出す
- タグを使ってる記事の数
- タグを消す
- 一覧から消す
- 記事についてるタグも消える
やりたいことはこんなところ
で、だ
タグを何個つけられるようになるかでも難易度が変わることに今更気が付いてしまった……遅いよ
なので、まずは3個固定でつけられるように作る。個数制限をなしにするのはその後で
次は必要なテーブルを作って、新規にタグをつけられるようにするよ
ブログアプリ⑦(記事を編集・削除しよう)
一度投稿した記事を編集or削除できるようにするよ
ところで、記事投稿でつくったコレ使いまわしたいね
……
部分テンプレ〜!テッテレー
まずはnewのビューファイルに直接書いたフォーム部分を切り出したげる
views/articles/_form.html.haml = form_for @article do |f| = f.text_field :title, placeholder: "タイトルだよ" %br = f.text_area :text, placeholder: "本文だよ" %br = f.select :status, Article.article_statuses %br = f.submit "送信するよ"
空っぽになったnewのビューファイルではテンプレ化したファイルを呼び出すようにする
views/articles/new.html.haml = render partial: 'form'
さらに編集用のビューファイルを作って、同じテンプレファイルを呼び出す
views/articles/edit.html.haml = render partial: 'form'
さらにさらに送信ボタンの表示をアクションによって変えるよ
これを
views/articles/_form.html.haml = f.submit "送信するよ"
こうして
views/articles/_form.html.haml - if action_name == "new" = f.submit "送信するよ" - else = f.submit "更新するよ"
こうじゃ
new
edit
ついでに削除ボタンもつけちゃう
editの時だけ表示させたいので、elseの中に追加
views/articles/_form.html.haml - else = f.submit "更新するよ" = button_to "削除するよ", { action: "destroy", id: @article.id }, method: :delete, data: { confirm: "消す?" }
できたー
最後にコントローラの中身を少し綺麗にすればOK
controllers/articles_controller.rb class ArticlesController < ApplicationController before_action :set_article, only: [:show, :edit, :destroy] def index @articles = Article.where(status: 1).order("created_at DESC") end def new @article = Article.new end def create @article = Article.new(article_params) @article.save redirect_to new_article_path end def show end def edit end def update end def destroy @article.destroy redirect_to articles_path end private def article_params params.require(:article).permit(:title, :text, :status) end def set_article @article = Article.find(params[:id]) end end
これで最低限必要な記事の投稿・表示・編集・削除ができるようになった
次はタグ機能をつくるよ
ブログアプリ⑥(記事を表示しよう)
データを登録できたので、次は表示させる
記事一覧画面で表示するもの
- タイトル
- 記事の最初30文字くらい
- 最終更新日
記事詳細画面で表示するもの
- タイトル
- 記事全文
- 最終更新日
タグ機能やページ送りもつけたいけど、まずは最低限表示できるようにしよう
コントローラでビューに渡すデータを取得して、ビューでデータを表示させるよ
記事一覧
controllerで、Articleのデータの中でstatusが1のデータを登録日降順に表示させる
controllers/articles_controller.rb def index @articles = Article.where(status: 1).order("created_at DESC") end
せっかくなので部分テンプレを使ってみる
views/articles/index.html.haml = render partial: 'article', collection: @articles
views/articles/_article.html.haml %ul = link_to "/articles/#{article.id}" do %li = article.title %li = article.text.truncate(30, omission: "...続きを見る") %li = article.created_at.to_s(:date)
ひとまずこんな感じにした
textとcreated_atは少し頑張ったので記録
text
truncate
というヘルパーメソッドを使うと、簡単に途中の文字まで表示することができる
デフォルトだと文字数30文字、末尾に「...」が表示される
truncate - リファレンス - - Railsドキュメント
ビューに記述するだけでできるなんて、ヘルパーメソッドってほんと便利
created_at
まず、何も設定しない状態だと、以下のように表示される
直したい点としては2つ
順に直していこう
日本時間で表示
意外と簡単!以下のように修正すればOK
config/application.rb config.time_zone = 'Tokyo'
こちらの記事を参考にしたよ
日付だけ表示
調べたところ2つ方法があった
strftime
メソッドを使う- 日付のフォーマットを変える
strftimeメソッドは簡単に使える
strftime - リファレンス - - Railsドキュメント
ただ、日付を表示したいところに全部書いていくのは面倒なので、フォーマットを変えちゃう
config/initializers/time_formats.rb Time::DATE_FORMATS[:default] = '%Y年%m月%d日 %H時%M分' Time::DATE_FORMATS[:datetime] = '%Y年%m月%d日 %H時%M分' Time::DATE_FORMATS[:date] = '%Y年%m月%d日' Time::DATE_FORMATS[:time] = '%H時%M分%S秒' Date::DATE_FORMATS[:default] = '%Y年%m月%d日' ※ファイルがなかったので新規作成
サーバを再起動して設定を適用
あとは表示させたいやつを記述すればOK
= article.created_at => 2018年12月02日 16時00分 = article.created_at.to_s(:date) => 2018年12月02日
曜日を日本語表記にもできそうだけど、ひとまずこれでOK
こちらの記事を参考にしたよ
記事詳細
記事一覧とほとんど同じかな
controllers/articles_controller.rb def show @article = Article.find(params[:id]) end
views/articles/show.html.haml %ul %li = @article.title %li = @article.text %li = @article.updated_at.to_s(:date)
次は、投稿した記事の編集と削除をできるようにしよう
ブログアプリ⑤(記事を投稿できるようにしよう)
ビューからデータを送信して、データベースに保存する機能をつくるよ!
View
タイトル、本文、公開or下書きを選ぶ、送信ボタンを置いた
views/articles/new.html.haml = form_for @article do |f| = f.text_field :title, placeholder: "タイトルだよ" %br = f.text_area :text, placeholder: "本文だよ" %br = f.select :status, Article.article_statuses.keys.to_a %br = f.submit '送信するよ'
なおビューにstatusセレクトボックスの選択項目をベタがきしたくなかったので、modelファイルにenumで項目を書いてビューで呼び出すようにした
models/article.rb class Article < ApplicationRecord enum article_status: { "公開する": 1, "下書きする": 2 } end
Controller
データを新規追加するためにcreateアクションでインスタンスの生成と保存する処理、あとストロングパラメーターを設定する
controllers/article_controller.rb class ArticlesController < ApplicationController def create @article = Article.new(article_params) @article.save end private def article_params params.permit(:title, :text, :status) end end
よーし試しにデータ登録してみるぞ!
なんでや!
いやいや落ち着いてコンソールを見ようね
いくつか気になるとこがあるね
Unpermitted parameter: ... :article, ...
とあるのでarticleモデルが許可されてない?- Parametersの
status
で文字が送られてる。本当は番号を飛ばしたい - MySQLが動いたあと、createアクションのテンプレート無いよって言われてる。ごめんて
上から順に解決していこう
Unpermitted parameter
ストロングパラメーターを修正。articleモデルを許可してあげるイメージ
controllers/article_controller.rb def article_params params.require(:article).permit(:title, :text, :status) end
詳しくはここを見よう
status
で文字が送られてる
ここでやりたいことは下の2つ
- DBに番号で登録する
- 日本語で表記する
で、1はできたものの2ができなかった
gemのenum_helpを使ってみたもののうまくいかなかったんだよねー。しかもそこまで重要ではないので、妥協して1だけでよいものとして以下のように修正
views/articles/new.html.haml = f.select :status, Article.article_statuses
models/article.rb enum article_status: { active: 1, archive: 2 }
createアクションのテンプレート無いよ
ひとまずnew(記事新規作成)の画面に戻るようにした
記事一覧or記事新規作成を選べるようにしたいなー
controllers/article_controller.rb def create @article = Article.new(article_params) @article.save redirect_to new_article_path end
よーし、今度こそデータ登録するぞ!
送信するよ
できたー!
次は保存したデータをビューで表示するようにするよ
ブログアプリ④(記事投稿機能を作る準備をしよう)
アプリケーションの素はもう作ってあるので、データベースをつくる
$ rake db:create Created database 'myblog_development' Created database 'myblog_test'
できたー
続けてArticleモデルを作成
なおrails model
は新しくテーブルを作る時、rails g migration
は作成済みのテーブルを修正・削除したい時に使うものと捉えてる
$ rails g model article title:string, text:text, status:integer Running via Spring preloader in process 85796 invoke active_record create db/migrate/20181126024341_create_articles.rb create app/models/article.rb invoke test_unit create test/models/article_test.rb create test/fixtures/articles.yml
よしよし
できあがったマイグレーションファイルを見てみる
お゛お゛ん゛!?カンマが変なとこについてる!??
落ち着いてrails d model
で一旦削除
で、今度はこれ
$ rails g model article title:string text:text status:integer
できあがったのがこちら
複数カラムまとめて作るからカンマ入れたけど、いらなかったんだねぇ
このマイグレーションファイルを元にテーブルつくるよ
$ rake db:migrate == 20181126024931 CreateArticles: migrating ========================= -- create_table(:articles) -> 0.0384s == 20181126024931 CreateArticles: migrated (0.0386s) ================
できたー
さらにArticleコントローラを作成
何もオプションを設定しないとhelperやcoffeeなどの使わないファイルも作成されるので、それは作らないようにする
ただし書き方がわからず、このコマンドで試しに実行したら作成されちゃった
$ rails g controller article --assets:none --helper:none
この記事で見た通り、config/application.rbに記載してあげるしかないのかなぁ。でもrailsドキュメントにはオプションとして載ってるから書き方の問題な気がする
config/application.rb module Myblog class Application < Rails::Application config.generators do |g| g.helper false g.javascripts false g.stylesheets false g.test_framework false end end end
これでもう一度コントローラ作成
$ rails g controller articles Running via Spring preloader in process 40742 create app/controllers/articles_controller.rb invoke haml create app/views/articles invoke assets invoke coffee invoke scss
必要なファイルだけできたー!
rails g scaffold
すればモデル・コントローラ・ビューを一通り作成できるのだけどね
不要なファイルが多くあるとどれを使えば分からなくなるので、今は必要最低限のものだけ作るようにする
最後にルーティングの設定とビューファイルを作って、画面が表示されることを確認しよう
config/routes.rb Rails.application.routes.draw do root 'articles#index' end
controllers/articles_controller.rb class ArticlesController < ApplicationController def index end end
views/article/index.html.haml を作成 "Hello world!"
準備完了
rails s
でサーバを起動してローカル環境に接続
できたー
これにて準備はOK
次は記事の投稿と表示ができる機能をつくるよ
ブログアプリ③(設計しよう)
少し日を置いたら入れたい機能が増えてしまった
とはいえ心の向くまま手をつけていては終わらないので、最低限実装する機能を決める
まずはそこからだ
前提
- 記事は誰でも見られる
- 投稿画面などは自分だけが見られるようにする(URLを秘匿、IDとパスワードでログインしてから操作)
つくる
- 記事を投稿する
- 記事を編集・削除する
- 記事にタグをつける
- 月別アーカイブ
つくりたい
- 記事を下書き状態と公開状態にできる
- 記事にコメントする
- 記事に絵文字を投げる
- 記事をマークダウンで書く
- 画像を投稿する(初めは1枚でいい。できれば複数)
- アプリ内検索機能
機能を元にデータベースの設計を考える
発生する情報は?
- 記事タイトル
- 記事本文
- 下書きor公開のステータス
- タグ一覧
- 記事⇔タグの関連
- コメント
- コメントした人の名前
- 絵文字一覧
- 記事⇔絵文字の関連
- 画像一覧
- 記事⇔画像の関連
テーブルにすると?
- 記事テーブル
- タイトル
- 本文
- 状態
- タグ一覧テーブル
- 記事とタグの中間テーブル
- コメントテーブル
- 本文
- コメントした人
- コメント先の記事
- 絵文字テーブル
- 記事と絵文字の中間テーブル
- 画像テーブル
- 画像情報(URL?)
- 画像を投稿した記事
ER図かいた
今わからないこと
考え始めたらまた出てくるだろうけど、現時点で実装方法が全然イメージできないのはこの二つ
- 画像を本文中の好きな場所に挿入する方法
- 絵文字だけ投げる方法(Slackをイメージ)
それじゃあ最低限のものから作っていこう
初めは記事を投稿して見られるようにするところから
なおデザインはあとから考える
スクールのカリキュラムで某フリマアプリのコピーサイトを作ったときフロントから作り始めたので、今度はバックから作る