宮崎勉強会 Advent Calendar 15日目の記事です。勉強会の中では年上の方なので、「枯れた」技術の良さを再確認するという主旨で、私の好きなRubyとRails、そのオススメのgemを幾つか紹介します。(本当はRails6の新機能を紹介する記事を書くつもりでいたんですが、環境構築で手こずって路線変更しています。6を使いたいけど、まだ導入のハードルが高かった…)
今回使用するRailsのバージョンは5.2.4です。vagrant上に構築したUbuntuでコマンドを実行しています。
$ rails -v
Rails 5.2.4
まずは、新しいプロジェクトを作成します。今回は wiki
という名前にしました。生成されたプロジェクトのディレクトリに入って、データベースの初期化とサーバの立ち上げもします。PostgreSQLを指定しているのは、このあとherokuというプラットフォームに載せてみようとしてるからです。
rails new wiki --database=postgresql
cd wiki/
rails db:create
rails s -b 0.0.0.0
ブラウザで http://localhost:3000 にアクセスすると以下のような画面が表示されます(vagrantで仮想ネットワークを使っている場合はlocalhostの部分が192.168.33.10などのIPになります)。
続けてこのアプリ上で管理したいテーブルの定義をします。 page
という名前のモデルに
title,body,published
という3つのフィールドを定義しました。
rails g scaffold page title body published:boolean
rails db:migrate
ホストのルート(URLのホスト名以下に何も書かない状態)からアクセスできるように、rootを定義しておきます(先程のRailsの画面が見えなくなる代わりに新しく作ったモデルの一覧ページが表示されるようになります)。
root to: 'pages#index'
このモデルを使って色んなgemの紹介をしていこうと思います。
markdownを使ってみる(redcarpet)
ここ(qiita)でも使っているMarkdown記法のテキストをhtmlにパースしてくれるのが redcarpet です。Gemfileに以下のバージョンを登録しました(Gemfileを更新したらbundle
を実行してください、これ以降も同様です)。
gem 'redcarpet', '~> 3.5'
直接Markdownとは関係ないですが、複数行のテキスト入力をするために、body
フィールドの編集エリアを text_field から text_area に変更します。
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
Redcarpetのパーザを使うためのヘルパメソッドを定義します。
def markdown(text)
unless @renderer
@renderer = Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: true, tables: true)
end
@renderer.render(text).html_safe
end
このメソッドでbody
の出力を囲うと、Markdownで保存されたテキストがHTMLとして整形されて出力されます。
<p>
<strong>Body:</strong>
<%= markdown(@page.body) %>
</p>
変更履歴を管理してみる(paper_trail)
paper_trailは、モデルの変更履歴(生成,更新,削除)を記録してくれます。papertrail(アンダースコアなし)という似たgemが存在するので注意してください。
gem 'paper_trail', '~> 10.3', '>= 10.3.1'
バージョン履歴を保存するテーブルを作ったりなどするために、以下のコマンドを実行します。
rails generate paper_trail:install
rails db:migrate
バージョン管理を行いたいモデルにhas_paper_trail
と記載します。
class Page < ApplicationRecord
has_paper_trail
end
これだけで、モデルの各操作に対する履歴が保存されるようになります。例えば、最初に「1」という内容で作成されたpageモデルが、続けて「2」「3」と2回更新された場合、以下のように3つのバージョン履歴が残っていて、それぞれの時点で保存されていた値を参照することが可能です。
irb> p = Page.last
irb> p.body
=> "3"
irb> p.versions[2].reify.body
=> "2"
irb> p.versions[1].reify.body
=> "1"
irb> p.versions[0].reify
=> nil
IDをベースに記録されているため、モデルが削除された場合でも、同一IDのモデルを新しく作ってから、versionsを参照すると過去の状態を参照することができます。以下の例では一度削除したモデルを削除直前の状態に戻しています。
irb> p = Page.new(id:3)
irb> p = p.versions.last.reify
irb> p.save
=> true
devise
などのgemと組み合わせると「誰が操作したか」という記録も合わせて保管できます。
画像をアップロードしてみる(active_storage)
Rails5.2で導入された新しい機能です。追加のgemは必要なく、以下のコマンドで有効化できます。
rails active_storage:install
rails db:migrate
今回は、pageモデルに複数の画像(images)を追加出来るようにしてみました。
class Page < ApplicationRecord
has_many_attached :images
ファイルをアップロードするためのフィールドを追加します。multiple: true
を忘れずに。
<div class="field">
<%= form.label :images %>
<%= form.file_field :images, multiple: true %>
</div>
コントローラでパラメタを受け取れるようにします。
def page_params
params.require(:page).permit(:title, :body, :published, images:[])
end
アップロードされたファイルを表示する部分です。
<% if @page.images.attached? %>
<% @page.images.each do |i| %>
<%= image_tag i %>
<% end %>
<% end %>
最終的にはAWSのS3などオブジェクトストレージに繋いで使うことを想定されているようですが、ひとまずこれだけでローカルディスクに画像などのアップロードされたファイルが貯められるようになります。
レスポンシブにしてみる(bootstrap)
Bootstrapはレスポンシブ対応のウェブサイトを構築するのに便利なライブラリです。色んなインストール方法がありますが、gemを入れてみます。
gem 'bootstrap', '~> 4.4.1'
gem 'jquery-rails'
bootstrap-rubygemのREADMEに従って幾つか設定の調整が必要です。例えば、Rails5.2では jquery-rails も一緒にインストールが必要です。
application.cssの代わりにapplication.scssを使用します。コピーする場合、*= require
が使えないので注意してください。
@import "bootstrap";
jsのインストールも必要です。
//= require jquery3
//= require popper
//= require bootstrap-sprockets
これでbootstrapが使える状態になりますが、(昔のgemにはあった気がする)自動的にスタイルを適用するgeneratorなどは見当たらないので、地道にクラスをあてて行きましょう(多分、要調査)。
アイコンを使ってみる(font-awesome-sass)
前述のBootstrap3.xまではglyphiconsというアイコンセットが一緒に使えていたのですが、4になってからどうも使い方がややこしくなっている感じです。Font Awesomeという別のセットをインストールします。
gem 'font-awesome-sass', '~> 5.12.0'
類似のgemにfont-awesome-rails
というものがあって、こちらの方がダウンロード数が多いのですが、更新が止まっているようで最近はこちらが主になっているのかな?という感じでした。
任意のscss内にインポートします。
@import "font-awesome-sprockets";
@import "font-awesome";
iconというヘルパ関数を使って、以下のようにアイコンを使用することができます。普通にhtml(<i class="fas fa-flag"></i>
)を書いてもOKです。
<%= link_to icon('fas', 'flag')+' New Page', new_page_path %>
ユーザ管理してみる(devise)
Deviseというgemを使います。
rails g devise:install
rails g devise user
インターネットに公開してみる(heroku)
ここまで作ったアプリをherokuに乗せてみましょう(アカウントの作成とherokuコマンドのインストールは省略しています)。一番シンプルには、以下のコマンドを順番に実行するだけです。
heroku login
heroku create
git push heroku master
heroku run rake db:migrate
createの際に名前を指定しないと、ランダムな単語の組み合わせが割り当てられます。今回は以下のURLでアプリケーションが起動されました。
※ active_recordの保存先をlocalに指定しているため、データが永続化されないherokuのサーバが再起動される度に画像が消えてしまいます
まとめ
思いつくままに幾つかの機能(gem)を紹介してみました。詳しい使い方はそれぞれの公式ドキュメントを参照してみてください。Railsの真価は、「こういうときはこのgemを使ったらいいや」というストックが個人の中に溜まってきてから発揮されると感じています。デフォルトのCRUDはページ遷移を基本とした古風なインターフェースですが、これだけでも仕組み化の手助けになる場面は多いかなと思います。
参考リンク
- https://rubygems.org/
- https://github.com/vmg/redcarpet
- https://github.com/paper-trail-gem/paper_trail
- Railsのプロジェクトにgem 'redcarpet' を用いてマークダウンエディタを導入してみた
- 【Rails 5.2】 Active Storageの使い方
- https://railsguides.jp/active_storage_overview.html
- Ruby | Heroku Dev Center
- Active Storage Overview
- Active Storage on Heroku | Heroku Dev Center
- docker-composeでRails5.2開発環境