環境
- OS: macOS 12.3.1(21E258)
- Ruby: 3.1.3
- Rails: 7.0.4
Railsアプリの作成する
rails new images
Active Storageのインストール
rails active_storage:install
Copied migration 20221227045939_create_active_storage_tables.active_storage.rb from active_storage
マイグレーション
rails db:create db:migrate
Database 'db/development.sqlite3' already exists
Database 'db/test.sqlite3' already exists
== 20221227045939 CreateActiveStorageTables: migrating ========================
-- create_table(:active_storage_blobs, {:id=>:primary_key})
-> 0.0010s
-- create_table(:active_storage_attachments, {:id=>:primary_key})
-> 0.0008s
-- create_table(:active_storage_variant_records, {:id=>:primary_key})
-> 0.0005s
== 20221227045939 CreateActiveStorageTables: migrated (0.0023s) ===============
最初の画面を作る
今回は写真を投稿する画面を1つだけ作る。
- routes.rbにrootを追加
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
root "posts#new"
end
- app/controllers/posts_controller.rbを作成
class PostsController < ApplicationController
def new
end
end
- app/views/posts/new.html.erbを作成
<h1>Example Image Uploader</h1>
動作確認
bin/rails s
画像を保持するモデルを作成
ここでは、Post(投稿)というモデルを作って、1つのPostに対して複数の写真(photos)をアップロードできるようにする。
rails g model Post
invoke active_record
create db/migrate/20221227051214_create_posts.rb
create app/models/post.rb
invoke test_unit
create test/models/post_test.rb
create test/fixtures/posts.yml
- app/models/post.rbを開き、has_many_attachedを追加
class Post < ApplicationRecord
has_many_attached :photos
end
マイグレーションを実行する
rails db:migrate
== 20221227051214 CreatePosts: migrating ======================================
-- create_table(:posts)
TRANSACTION (0.1ms) begin transaction
(1.7ms) CREATE TABLE "posts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL)
-> 0.0041s
== 20221227051214 CreatePosts: migrated (0.0042s) =============================
画面にアップロードするフォームを作成
- app/views/posts/new.html.erb
<h1>Example Image Uploader</h1>
<%= form_with model: @post do |f| %>
<%= f.file_field :photos %>
<%= f.submit %>
<% end %>
動作確認する。こんな感じで表示される。
アップロードの処理を書く
- config/routes.rbに
POST /postsのルーティングを追加
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
root "posts#new"
resources :posts, only: [:new, :create]
end
- app/controllers/post_controller.rbを作成。
#newメソッドと#createメソッドを書く
class PostsController < ApplicationController
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
@post.save
redirect_to root_path
end
private
def post_params
params.require(:post).permit(:photos)
end
end
Postにフィールドを追加する
バリデーションエラーが発生した場合の動作のチェックのためにPostモデルにフィールドを追加する。
ここではタイトル(title)という文字列フィールドを追加することにする。タイトルは20文字を超えるとバリデーションでエラーになるようにする。
rails g migration AddTitleColumnToPosts
- config/db/..._add_title_column_to_posts.rb
class AddTitleColumnToPosts < ActiveRecord::Migration[7.0]
def change
add_column :posts, :title, :string
end
end
- マイグレーション
rails db:migrate
== 20221227054700 AddTitleColumnToPosts: migrating ============================
-- add_column(:posts, :title, :string)
-> 0.0010s
== 20221227054700 AddTitleColumnToPosts: migrated (0.0010s) ===================
- app/models/post.rb
バリデーションを追加
class Post < ApplicationRecord
has_many_attached :photos
validates :title, presence: true, length: { maximum: 20 } # ここを追加
end
- app/controllers/posts_controller.rb
バリデーションエラーの時はリダイレクトではなく、renderするように変更
...
def create
@post = Post.new(post_params)
if @post.save
redirect_to new_post_path
else
render :new, status: 400
end
end
...
- app/views/posts/new.html.erb
画面にバリデーションエラーの表示を追加
<h1>Example Image Uploader</h1>
<%= form_with model: @post do |f| %>
<ul>
<% @post.errors.full_messages.each do |m| %>
<li><%= m %></li>
<% end %>
</ul>
<div><%= f.text_field :title %></div>
<div><%= f.file_field :photos %></div>
<div><%= f.submit %></div>
<% end %>
