質問投稿サイトの作成(1/3)
ここでは,投稿フォームから新規の質問ができるようにする質問する人の名前(name),質問のタイトル(title),質問(content)を入力できるようにする
108.新規railsプロジェクトの作成
例えば,rails_projectsというフォルダを作成し,RubyとRailsのバージョンを確認.
$ cd rails_projects $ ruby -v $ rails -v Rails 5.2.x $ rails _5.2.x_ new qanda cd qanda
追加設定
Gemfileに以下を追加
gem 'sqlite3', '~> 1.3.6' #追加
bundle install
データベースの作成
$ rails db:create
'db/test.sqlite3'
が生成される
109.Questionsコントローラーの作成
質問を管理するコントローラーを作成
$ rails g controller questions index show new edit
Running via Spring preloader in process 4071 create app/controllers/questions_controller.rb route get 'questions/index' get 'questions/show' get 'questions/new' get 'questions/edit' invoke erb create app/views/questions create app/views/questions/index.html.erb create app/views/questions/show.html.erb create app/views/questions/new.html.erb create app/views/questions/edit.html.erb invoke test_unit create test/controllers/questions_controller_test.rb invoke helper create app/helpers/questions_helper.rb invoke test_unit invoke assets invoke coffee create app/assets/javascripts/questions.coffee invoke scss create app/assets/stylesheets/questions.scss
110.Questionモデルの作成
質問を保存するquestionモデルを作成
rails g model question name:string title:string content:text
Running via Spring preloader in process 4209 invoke active_record create db/migrate/XX_create_questions.rb create app/models/question.rb invoke test_unit create test/models/question_test.rb create test/fixtures/questions.yml
class CreateQuestions < ActiveRecord::Migration[5.2] def change create_table :questions do |t| t.string :name t.string :title t.text :content t.timestamps end end end
rails db:migrate
== XX CreateQuestions: migrating ================================== -- create_table(:questions) -> 0.0063s == XX CreateQuestions: migrated (0.0065s) =========================
DB構造の確認のため
rails dbconsole sqlite> .schema テーブル名(今はquestions) sqlite> .q
111.ルーティングの設定
config/routes.rb に自動でルーティングが作成されているので,削除かコメントアウト
次の一般的なアプリケーションに必要なルーティングで自動で用意してくれるresourcesメソッドを使う
Rails.application.routes.draw do get 'questions/index' #削除 get 'questions/show' #削除 get 'questions/new' #削除 get 'questions/edit' #削除 resources :questions #追加 end
112.rootメソッドの設定
config/routes.rbに以下を追加
root 'questions#index' #追加 resources :questions
113.質問一覧ページの作成
ここでは質問の「ID」と「タイトル」を一覧表示する.
コントローラ
def index @questions = Question.all end
view
以下を追加
<h2>Questions</h2> <div class="row"> <div class="col-md-12"> <table class="table table-striped"> <thead class="thead-light"> <tr> <th>ID</th> <th>Title</th> <th>Menu</th> </tr> </thead> <tbody> <% @questions.each do |question| %> <tr> <td><%= question.id %></td> <td><%= question.title %></td> <td>[Edit][Delete]</td> </tr> <% end %> </tbody> </table> </div> </div>
投稿がないため、ヘッドの行だけの表示だけになり,かなり味気ない
114.シードファイルを使った初期データの挿入
questionsテーブルにはデータが何も入っていないので,初期データをいれる。db/seeds.rbに以下を追加
Question.create(id: 1, name: "Test name 1", title: "Test question 1", content: "Test content 1" ) Question.create(id: 2, name: "Test name 2", title: "Test question 2", content: "Test content 2" ) Question.create(id: 3, name: "Test name 3", title: "Test question 3", content: "Test content 3" )
rails db:seed
rails c > Question.all
115.Bootstrapの導入
フロントエンド開発を効率的に行われるCSSフレームワーク.無償bootstrapはgemを使って導入できる.
bootstrap4を使う.詳細はGitHub参照
Gemfile
#一番下などに追加 gem 'bootstrap', '~> 4.1.1' gem 'jquery-rails', '~> 4.3.1'
bundle install
application.css
application.cssの拡張子をcssからscssに変換(questions.cssも自動的にscssになる)
mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss
sassはcssを便利に実装するためのスクリプト言語
applications.scss
に以下を追加@import "bootstrap";
application.js
GitHubの「bootstrap-rubygems」の下,「Add Bootstrap dependencies and Bootstrap to your applications.js:」 の3行をコピーし,assets/javascripts/application.jsファイルの//= require_treeの前にはりつけ
//= require rails-ujs //= require activestorage //= require turbolinks <!-- 追加ココから --> //= require jquery3 //= require popper //= require bootstrap-sprockets <!-- ココまで --> //= require_tree .
application.htm.erb
一覧表示を中央ぞろえにするため以下を追加
<body> <div class="container"> <!-- 追加 --> <%= yield %> </div> <!-- 追加 --> </body>
かなり見栄えがよくなった
116.新規質問の投稿
新規質問の投稿フォームを作る。questions/new.html.erbファイルに以下を追加
<div> <div class="col-md-4 offset-md-4"> <h2 class="text-center">New question</h2> <%= form_with model: @question, local:true do |f| %> <div class="form-group"> <label>Name</label> <%= f.text_field :name, class: "form-control" %> </div> <div class="form-group"> <label>Title</label> <%= f.text_field :title, class: "form-control" %> </div> <div class="form-group"> <label>Content</label> <%= f.text_field :content, class: "form-control" %> </div> <div class="text-center"> <%= f.submit "Save", class: "btn btn-primary" %> </div> <% end %> </div> </div>
form_with
form_with, text_field, submitという各メソッドは,ホームヘルパーで,開発者が煩雑になりがちなhtmlをかかなくても,フォームに関するhtmlを自動で生成してくれる.form_withはrails5.1から導入された新しいメソッド.form_forとform_tagの利用は非推奨form_withで生成されたフォームはデフォルトで非同期通信で行われるのだが,local:trueで非同期通信を無効にしている。
form_with model: @モデル名 do |f|
formは渡されたものによって,行うHTTPメソッドとアクションを判断してくれる.モデルに入っているものが「①新規に作られたものの場合」と「②既存のもののを呼び出した場合」で処理が変わる.①新規に作られたものが渡された場合(今の場合) newアクションから渡されたものがこれにあたる.Railsは渡されたモデル(@question)の中身が空であるであることから,createメソッドを呼び出してくれる.また,form_withで生成されたフォームはデフォルトで非同期通信で行われるが,local:trueで非同期通信を無効にしている.
Bootstraps
- Bootstrapでは横幅を12分割したグリッドシステムを採用
- class = “container”(固定枠)または”container-fluid”(流動枠)の中に書く
- col-md-12: 「.col-画面幅-グリッド数」 md:「画面幅がMidium」
- 例えば、col-md-4と記述すると,画面幅がMiduim以上のときはグリッドを4個持つカラムを生成
グリッドに関しては次のサイトが分かりやすい
websae.net
コントローラ側を実装していないので,「Save」を押しても何も反応はない
117.投稿データの保存
def new @question = Question.new end #追加ココから def create @question = Question.new(question_params) if @question.save redirect_to root_path, notice: "Success!" else flash[:alert] ="Save error!" render :new end end #ココまで #一番下に追加 private def question_params params.require(:question).permit(:name, :title, :content) end #ココまで end
redirect_to
で root_path(一覧表示)にとばす.失敗すれば,
render
でnew(新規質問入力)にとばす.ちなみに、Prefixとコントローラのアクションは次の関係
Prefix Verb URI Pattern Controller#Action root GET / questions#index questions GET /questions(.:format) questions#index POST /questions(.:format) questions#create new_question GET /questions/new(.:format) questions#new
render action: :new
とかいてもよい.renderに関しては次が分かりやすい
pikawaka.com
実際に投稿してみる
118.ストロングパラメーター
フォームから送られてきたデータは信頼できないので,question_paramasメソッドを使って指定したパラメータだけを登録対象とする.
フォームから送られてきた:questionのデータのうち:name, :title, :contentを採用.
paramsの中身に関して,ここではモデルを渡しているので,params[:question][:name]と階層構造になっていることに注意!それによりストロングパラメータの設定で,.require(:question)のように一度仲介をはさむ必要がある。
119.paramsに入るデータをデバッグ
gem 'byebug'
bundle install
コマンドプロンプトで,フォームから送られた変数に入っている値を確認できる(byebug)params.
nextを入力してEnterを押すと次の行にいく.
quitで終了
120.バリデートの追加
class Question < ApplicationRecord validates :name, presence: true validates :title, presence: true validates :content, presence: true end
121.エラーメッセージの表示
<body> <div class="container"> <!-- 追加ココから --> <% if flash[:notice] %> <p class = "text-success"><%= flash[:notice] %></p> <% end %> <% if flash[:alert] %> <p class="text-danger"><%= flash[:alert] %></p> <% end %> <!-- ココまで --> <%= yield %> </div> </body>