I implemented it so that I can upload multiple images using carrierwave.
carrierwave is a library that allows you to easily implement image upload functions from Rails applications. This time, I used carrierwave ver2.1.0.
First, install the Gem below.
My app / Gemfile
gem 'carrierwave'
gem 'mini_magick'
Generate an uploader.
rails g upload image
This will generate the following files: If you want to customize in this file, add processing.
app/upload/image_upload.rb
So, I made the settings as below.
My app /app/upload/image_upload.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
process resize_to_fill: [1000, 1000]
version :thumb do
process resize_to_fit: [223,223]
end
version :swiper do
process resize_to_fit: [400, 400]
end
version :thumbnil do
process resize_to_fit: [100, 100]
end
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_whitelist
%w(jpg jpeg gif png)
end
end
How did you add the settings?
include CarrierWave::MiniMagick
I wanted to resize the image when uploading, so I installed minimagick. Since it is commented out when image_upload.rb is generated, # is deleted and it is described as a processing code. minimagick is a Ruby interface for imagemagick, a C program. This allows you to use methods for image resizing.
When uploaded, the process below cuts out at 1000x1000px, then a version called thumb is created and scaled to 223x223px. Similarly, versions called sweeper and thumbnil are created and scaled to each version.
However, it is not desirable to increase the version too much depending on the team development.
process resize_to_fill: [1000, 1000]
version :thumb do process resize_to_fit: [223,223] end
version :swiper do process resize_to_fit: [400, 400] end
version :thumbnil do process resize_to_fit: [100, 100] end
This is where the image is saved when it is uploaded. The default is listed. It is placed like "public / uploads / specified model name / specified model column name / model ID / image and image created in each version". If you change it, you can overwrite it.
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
This is also commented out by default, so it is described so that it can be processed. You can specify a whitelist of allowed extensions. Uploading extensions other than jpg, jpeg, gif, and png will invalidate the record.
def extension_whitelist
%w(jpg jpeg gif png)
end
This is the end of the explanation of the settings, and then the parent post table and the child image table are created. The table is divided into post and image in order to support multiple posts.
posts |
---|
content |
images |
---|
url |
post_id |
$rails g model Post content:text
$rails g model Image url:string post:reference
What I stumbled upon here was that in my case I handled the json type when creating the image model. Originally, I wanted to create a specification that allows multiple posts by creating an image column in the post table, but since I changed it to create a new image table and save it, I later learned that it is not necessary to make it a json type. I noticed. So, if you want to handle multiple images in one table here, you can use json type and design it so that you can handle multiple images in one object record. In my case, I created another table and left it as json type, but unless there is a specific reason, it is recommended to create it as string type.
Create a migration file and update the database.
$rails db:migrate
Add the following description to the model file.
My app /app/model/image.rb
class Image < ApplicationRecord
belongs_to :post
mount_uploader: url, ImageUploader # Mount the data you want to use the upload function. end
My app /app/mode/post.rb
class Post < ApplicationRecord
validates :content, presence: true, length: { maximum: 1000 }
has_many :images, dependent: :destroy
If you post accepts_nested_attributes_for: images #post, you will be able to post images at the same time. end
It should be noted here that when using accepts_nested_attributes_for, the images_attributes column must be added to the strong parameter. It will be as follows.
My app /app/controller/post_controller.rb
def new
@post = Post.new
@image = @post.images.build
end
def create
@post = current_user.posts.new(post_params)
if @post.save
redirect_to posts_path, success: "posted" else flash [: danger] = "Posting failed" render :new end end
private
def post_params
params.require(:post).permit(:content, images_attributes: [:url])
end
You have now set up to pass multiple images as parameters. Next, let's think about how to allow multiple images to be posted in view. Here, I was addicted to various things. In the fields_for method, it is said that multiple posts can be posted by describing multiple: true in the second argument, but it does not work ,. So, as another method, I implemented it so that multiple posts can be made with javascript. This article was written very well, so I used it as a reference. → Qiita If you set according to this article, javascript will start and the program should run every time you upload.
Roughly speaking, it is a framework that makes it easy to implement the slide function.
First, set up the sweeper to be used in the application. There are several methods, but I introduced it using yarn. The introduction method and contents of this article in yarn were very easy to understand, so I used it as a reference. →Qiita
Introduce swiper with yarn.
$yarn add swiper
$yarn install
Check packege.json to see if it was installed. If you have not installed yarn, install yarn with the following command. (If you are using mac)
$brew installl yarn
After installing, describe as follows in application.js and application.scss.
My app /app/assets/stylesheets/application.scss
@import "swiper/swiper-bundle";
My app /app/assets/javascript/application.js
//= require swiper/swiper-bundle.js
//= swiper.js
Create a swiper.js file and write as follows. With swiper, you need to write and create the kind of slide method you want to add with swiper. Choose your preferred slide method from the swiper demo and copy the js code in the script below!-Initialize Swiper-from the source code. Script tags do not need to be included. In my case, I made a slide with pagination / dynamic bullets, so it looks like this: This js file name does not have to be swipe.js. If you want to change the file name, also change the file name described in application.js. Demo
My app /app/assets/javascript/swiper.js
var swiper = new Swiper(".swiper-container", {
pagination: {
el: ".swiper-pagination",
dynamicBullets: true,
},
});
Now that we're ready, let's actually implement it in view. Since it is an implementation example with pagination / dynamic bullet, if you choose another sliding method, please check the source code.
My app /app/views/posts/index.html.slim
.swiper-container.top-carousel
.swiper-wrapper(style="transform: translate3d(0px, 0px, 0px)")
- @post.images.each do |img|
.swiper-slide(style="width: 400px;")
= link_to post do
= image_tag img.swiper.url, class: "card-img-top"
.swiper-pagination
~ Omitted ~
= javascript_include_tag "application"
The important thing here is to write = javascript_include_tag "application" at the very end. If you forget to write this, sweeper will not start. You can write it in application.html.slim, but I write it only in the part of the page that requires sweeper. Also, this img.url.swiper.url calls the sweeper version of the image created by carrierwave.
You have now implemented swipe in your case.
Recommended Posts