Railsにこれから初めて触れる方を対象にしたチュートリアルです
Trix
に画像アップロード機能を作るチュートリアルになります
まず、rails new
を実行し、Railsアプリのひな型を作成します
rails new trix_image
次に、作成したRailsアプリのディレクトリへと移動します
cd trix_image
先ほどのrails new
でsqlite3
のインストールがエラーになっている場合は、以下のようにバージョンを修正します
gem 'sqlite3', '1.3.13'
その後、bundle install
を実行します
bundle install
rails g scaffold
コマンドを使い、Trix
で使用するCRUDを作成します
rails g scaffold post title:string content:text auther:string
次に、画像投稿用のCRUDを作成します
rails g scaffold photo image
その後、rails db:migrate
でマイグレーションを行います
rails db:migrate
Trix
を導入していきます
まずはGemfile
にTrix
を追加します
gem 'trix'
その後、bundle install
を実行します
bundle install
次に、app/assets/javascripts/application.js
に以下の行を追加します
//= require trix
また、app/assets/stylesheets/application.css
にも以下の行を追加します
*= require trix
app/views/posts/_form.html.erb
を以下のように変更します
<%= form_with(model: post, local: true) do |form| %>
<% if post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% post.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: 'post_content' %>
<trix-editor input="post_content"></trix-editor>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
最後に、app/view/posts/show.html.erb
を以下のように変更します
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= @post.title %>
</p>
<p>
<strong>Content:</strong>
<%= sanitize @post.content %>
</p>
<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>
Shrine
というアップロード用のgemを使用し、画像アップロード機能のひな型を作成します
まず、Gemfile
にShrine
を追加します
gem 'shrine'
その後、bundle install
を実行します
bundle install
その後、config/initializers/shrine.rb
を以下のように作成します
require "shrine"
require "shrine/storage/file_system"
Shrine.storages = {
cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"),
store: Shrine::Storage::FileSystem.new("public", prefix: "uploads/store"),
}
Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data
次に、app/views/photos/_photo.json.jbuilder
に以下の一行を追加します
json.image_url photo.image_url
アップロード用のモデルapp/models/image_uploader.rb
を作成します
class ImageUploader < Shrine
end
作成したモデルをPost
モデルにinclude
します
class Photo < ApplicationRecord
include ImageUploader[:image]
end
rails g migration
コマンドを使用して既存のimage
カラムをimage_data
カラムにリネームします
rails g migration RenameImageColumnToPhotos
作成したマイグレーションファイルを以下のようにします
class RenameImageColumnToPhotos < ActiveRecord::Migration[5.2]
def change
rename_column :photos, :image, :image_data
end
end
rails db:migrate
を実行し、マイグレーションを行います
rails db:migrate
後は、app/views/photos/_form.html.erb
を編集し、アップロードができるようにします
<%= form_with(model: photo, local: true) do |form| %>
<% if photo.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(photo.errors.count, "error") %> prohibited this photo from being saved:</h2>
<ul>
<% photo.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :image %>
<%= form.file_field :image, id: :photo_image %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
これで、画像のアップロードが実行できるようになりました
app/assets/javascripts/application.js
を以下のように修正します
function uploadAttachment(attachment) {
var file = attachment.file;
var form = new FormData;
form.append("Content-Type", file.type);
form.append("photo[image]", file);
var xhr = new XMLHttpRequest;
xhr.open("POST", "/photos.json", true);
xhr.setRequestHeader("X-CSRF-Token", Rails.csrfToken());
xhr.upload.onprogress = function(event) {
var progress = event.loaded / event.total * 100;
attachment.setUploadProgress(progress);
}
xhr.onload = function() {
if (xhr.status === 201) {
var data = JSON.parse(xhr.responseText);
return attachment.setAttributes({
url: data.image_url,
href: data.url
})
}
}
return xhr.send(form);
}
// Listen for the Trix attachment event to trigger upload
document.addEventListener("trix-attachment-add", function(event) {
var attachment = event.attachment;
if (attachment.file) {
return uploadAttachment(attachment);
}
});
これで、エディターに画像をペーストするだけで画像のアップロードができるようになります!