[Rails] Implement image posting function

Overview

While creating a bulletin board site in a Rails project, I had the opportunity to implement an image posting feature. I will leave the procedure here as a memorandum.

1. Creating an Image model

Create Model and migration file

There are two tables, posts table and ʻimage table. The post_id` column of the image table has a relation to the post table.

terminal


$ rails g model Image image_url:string post:references

Open the created migration file and check it.

db/migrate/Date and time_create_images.rb


class CreateImages < ActiveRecord::Migration[5.0]
  def change
    create_table :images do |t|
      t.string :image_url
      t.references :post, foreign_key: true

      t.timestamps
    end
  end

It seems that the migration file has been created without any problems.

Perform migration

terminal


$ rails db:migrate

Check Image Model

app/model/image.rb


class Image < ApplicationRecord
  belongs_to :post
end

** belongs_to: post ** is written because the references are set in the migration file.

Add relation to existing Post Model

Add ** has_many: images **.

app/models/post.rb


class Post < ApplicationRecord
  
  has_many :images #Add this line
end

With this, we were able to express a one-to-many relationship.

2. Use accepts_nested_attributes_for to enable updating of multiple models from one form

This time, I will register multiple models at once with one form so that images can be posted at the same time when posting a post. What is needed for that

__ · accepts_nested_attributes_for__

is. If you use this, you will be able to register has_many related child records at once.

Preparation for handling nested forms

You will create a nested form to register the tables together. Let's use a method called accepts_nested_attributes_for to make that possible.

Now, let's set accepts_nested_attributes_for. Add the settings to the Post model as follows.

app/models/post.rb


class Post < ApplicationRecord
  
  has_many :images
  accepts_nested_attributes_for :images #Add this line
end

edit posts controller

Add the settings to posts_controller.rb as well.

app/controllers/posts_controller.rb


class PostsController < ApplicationController

  def new
    @post = Post.new
    @post.images.build #Add this line
  end

  def create
    @post = current_user.posts.build(post_params)
    if @post.save
      flash[:success] = 'I posted a message.'
      redirect_to root_url
    else
      @posts = current_user.feel_posts.order('created_at DESC').page(params[:page]).per(10)
      flash.now[:danger] = 'Failed to post the message.'
      render 'posts/new'
    end
  end

  private
  
  def post_params
    params.require(:post).permit(:content, :security, images_attributes: [:image_url]) #Add this line
  end

@post.images.build And in params images_attributes: [:image_url] Was added. The values of the parameters allowed by the nested model are described using images_attributes: in params.

Nest in a form using fields_for

erb:views/posts/new.html.erb


<%= form_for(@post) do |f| %>
  <div class="form-group">
    <%= f.label :content, 'comment' %>
    <%= f.text_area :content, class: 'form-control', rows: 5, placeholder: 'Please enter a comment'  %>
  </div>
        
  <div class="form-group">
    <%= f.label :security, 'Security_Level' %>
    <%= f.number_field :security, class: 'hoge', min: 0, max: 100 %>
  </div>
          
  <%= f.fields_for :images do |i| %>  #Add to this line
    <%= i.file_field :image_url %>
  <% end %>
                
  <div class="text-right">
    <%= f.submit 'Post', class: 'btn btn-primary' %>
  </div>
<% end %>

Now, you can register multiple models at once with one form. Next, create an image upload function.

3. Install CarrierWave to allow you to upload images

Add the "Carrier Wave" gem to Gemfile.

Gemfile


gem 'carrierwave' #Image upload

Run bundle install.

terminal


$ bundle install

Creating an uploader

terminal


$ rails g uploader image

For image, set an appropriate name. This time, I named it image. When you execute the command

create app/uploaders/image_uploader.rb

And the image uploader was created.

Model association

Add the following to /models/image.rb and specify the column name in mount_uploader.

app/models/image.rb


class Image < ApplicationRecord
  belongs_to :post
  
  mount_uploader :image_url, ImageUploader #Add to this line
end

The image model has a column called image_url, which is designed to store the URL of the image. By specifying a column in mount_uploader, Carrierwave will automatically upload the image when updating the column and save the URL of the upload destination.

Display the image saved by Carrierwave in View

erb:view/posts/_posts.html.erb


 <div>
   <%= link_to post.user.name, user_path(post.user) %><span class="text-muted">posted at<% post.created_at %></span>
 </div>
 <div>
   <p><%= post.content %></p>
 </div>
 <div>
   <% post.images.each do |image| %>  
     <%= image_tag image.image_url.url %>  #Show here
   <% end %>
 </div>
 <div>
   <p>Security_Level <%= post.security %></p>
 </div>
        
 <div class="batton">
   <%= render 'favorites/favorite_button', post: post %>
   <% if current_user == post.user %>
     <%= link_to "Delete", post, method: :delete, data: { confirm: "Do you really want to delete this?" }, class: 'btn btn-danger btn-xs' %>
   <% end %>

The image posting function has been implemented.

At the end

You have now implemented the image posting function in your Rails project. There are some points that can be improved, such as posting multiple images, but for the time being, it's just a paragraph.

Thank you very much.

Recommended Posts

[Rails] Implement image posting function
Image posting function
How to implement image posting using rails
Flow to implement image posting function using ActiveStorage
Implement application function in Rails
[Rails] Implement User search function
Implement follow function in Rails
Continued ・ Flow to implement image posting function using ActiveStorage
How to implement image posting function using Active Storage in Ruby on Rails
[Rails] Implementation of image preview function
Implement simple login function in Rails
[Rails] Voice posting function ~ Cloudinary, CarrierWave
Implement CSV download function in Rails
Let's roughly implement the image preview function with Rails + refile + jQuery.
Image preview function
I tried to implement the image preview function with Rails / jQuery
Implement Rails pagination
[Rails] Category function
Rails follow function
[Rails] Image posting by CarrierWave [AWS EC2]
Multiple image upload function using Rails Carrierwave
[Rails] Notification function
[Rails] Implementation of image enlargement function using lightbox2
Posting function implemented by asynchronous communication in Rails
Implement star rating function using Raty in Rails6
[rails] tag ranking function
Implement Rails account BAN
Rails search function implementation
[Rails] Implement rake task
Implement markdown in Rails
[Ruby on Rails] Asynchronous communication of posting function, ajax
Implement post search function in Rails application (where method)
[Implementation procedure] Implement image upload function with Active Storage
[Rails] Implement credit card registration / deletion function in PAY.JP
Implement user follow function in Rails (I use Ajax) ②
Implement user follow function in Rails (I use Ajax) ①
Rails learning How to implement search function using ActiveModel
Try to implement tagging function using rails and js
Rails fuzzy search function implementation
Introduced graph function with rails
Search function using [rails] ransack
Implement login function in Rails simply by name and password (1)
[Rails 6] Implementation of search function
Implement LTI authentication in Rails
Implementation of image preview function
Implement login function in Rails simply by name and password (2)
[Rails] Implementation of category function
Rails image slides automatically [Swiper]
[Rails] Implement event end function (logical deletion) using paranoia (gem)
[Ruby on Rails] Implement login function by add_token_to_users with API
Implement category function using ancestory
[Rails] (Supplement) Implemented follow function
Login function implementation with rails
[Rails] EC site cart function
Implement import process in Rails
[Rails] Implementation of tutorial function
[Rails] How to implement scraping
[Rails] Implementation of like function
Implement login function simply with name and password in Rails (3)
[Rails] I tried to implement "Like function" using rails and js
Implement user registration function and corporate registration function separately in Rails devise