備忘録のため記述しています。
Carrierwave という gem の導入
carrierwaveuploader/carrierwave
Gemfile に以下を記述
gem "carrierwave", "~> 2.0"
終わったらターミナルにて bi
bundle install
Uploader の作成
bundle exec rails g uploader Images
下記が作成される。
images_uploader.rb
アップロードされるファイルの設定を色々弄れるけど今回は見送り。
MVC 設定
Post モデルに対して Memory というモデルで画像登録をできるようにしている
Model
Post
post.rb
class Post < ApplicationRecord
has_many :memories
accepts_nested_attributes_for :memories, allow_destroy: true
validates :title, presence: true
end
accepts_nested_attributes_for :memories の設定で posts_controller 上で memories を登録できるようにしている。
Memory
memory.rb
class Memory < ApplicationRecord
belongs_to :post
mount_uploader :image, ImagesUploader
end
mount_uploader は carrierwave の設定。これで簡単にアップロードできるようになる。
Controller
posts_controller.rb
posts_controller.rb
class PostsController < ApplicationController
def new
@post = Post.new
# @post.memories.build とすることで post に紐づいた memories を保存する準備が整う
@post_memory = @post.memories.build
end
def create
post = Post.new(post_params)
if post.save!
# 以下は memories に保存する処理。 each 文で複数の画像を保存可能。
params[:memories][:image].each do |image|
post.memories.create(image: image, post_id: post.id)
end
end
redirect_to root_path
end
private
def post_params
params.require(:post).permit(:title, memories_attributes: [:image]).merge(user_id: current_user.id)
end
end
View
new.html.erb
<%= form_for @post, local: true, html: {class: "form_area"} do |f| %>
<div class="form_area__field">
<%= f.text_area :title, id: "post_text", placeholder: "投稿内容を入力", rows: 10%>
<div class="form_area__image_field">
<%= f.fields_for :memories do |m| %>
<%= m.label :image, "画像" %>
<%= m.file_field :image, multiple: true, name: "memories[image][]" %>
<%= hidden_field :memories, :post_id, value: @post.id %>
<% end %>
</div>
<div class="form_area__hidden_field">
<%= hidden_field :post, :user_id, value: current_user.id %>
</div>
<div class="form_area__action">
<%= f.submit "投稿", class: "form_area__action__btn" %>
</div>
</div>
<% end %>
fields_for で1回の投稿で複数のクラスを保存できる。
multiple: true で複数の画像を投稿できるように設定している。
表示するには?
<% @post.memories.each do |m|%>
<%= image_tag m.image.url %>
<% end %>
上記で表示できる。
画像を追加するには? (2021年1月16日追記)
既に画像つきで投稿されている記事に対して画像を追加する機能を実装しました。
結果としてはすごくシンプルですが、どう実装したものかよくわからず苦戦しました。
機能
- 記事の内容が変更されたら記事のみ変更
- それ以外の場合画像が追加される
Controller
def update
post = Post.find(params[:id])
# 更新前の記事と params として渡された記事を比較している
if post.title != params[:post][:title]
post.update!(post_params)
else
post.save!
params[:memories][:image].each do |image|
post.memories.create(image: image, post_id: post.id)
end
end
redirect_to root_path
end
選択した画像を編集できた方がより良いと思いますが、こちらの機能はまた今度。。。