Upload multiple images To Rails 7 API - Active_storage : Part 1
Published: 2023-03-12 11:37:45

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9n801go8bw49d4l3myg4.PNG)
---
Uploading multiple images is a common task when building web applications. 

With the release of Rails 5.2, we were introduced to Active Storage, a framework for managing file uploads to a cloud storage service or the local disk. In this blog post, we will walk through how to upload multiple images to a Rails 7 API using Active Storage.

In this blog post, we will go through the steps to upload multiple images to a Ruby on Rails 7 API using Active Storage, a framework for managing file uploads to a cloud storage service or the local disk.

This blog post is divided into 2 parts

**Part 1 :** Backend API whit Rails 7
- Github link : [multiple-image-uploads-api](https://github.com/Chrissiku/multiple-image-uploads-api)

**Part 2 :** Frontend with React.js
- Github link : [multiple-image-uploads-client](https://github.com/Chrissiku/multiple-image-uploads-client)
- Blog post : [Part 2](https://dev.to/chrissiku/upload-multiple-images-to-rails-7-api-activestorage-part-2-4dll)


## Part 1 : Backend API

- First, we need to create a new Rails API application using the following command in your terminal:

```sh
rails new multiple-image-uploads --api -d postgresql 
```
- Then, navigate to the new application directory using the command
```sh
cd multiple-image-uploads
```

- Next, generate a Post model using scaffold. This model will be used to represent the posts that will contain the uploaded images:

```sh
rails g scaffold post
```
- After generating the Post model, we need to install Active Storage using the following command:

```sh
rails active_storage:install
```
This command will create the necessary database tables and migration files to enable Active Storage.

- Next, we need to update the Gemfile file to include two necessary gems: `image_processing` and `rack-cors`. Uncomment these gems and run bundle install to update all your gems.

```ruby
# [...]
gem "image_processing"
gem "rack-cors"
```
- To allow all origins to access the API, update the `cors.rb` file under `config/initializers`:

```ruby
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "*"

    resource "*",
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
```
- Now that Active Storage is installed, we can set up the Active Storage association in the Post model. In the `post.rb` file under `app/models/`, add the following code:

```ruby
class Post < ApplicationRecord
  has_many_attached :images
end
```
- With the association set up, we need to update the `posts_controller.rb` file to handle image uploads. Replace the contents of this file with the following code:

```ruby
class PostsController < ApplicationController
  before_action :set_post, only: %i[show update destroy]

  # GET /posts
  def index
    @posts = Post.all

    render json: @posts
  end

  # GET /posts/1
  def show
    render json: @post.as_json(include: :images).merge(
      images: @post.images.map do |image|
        url_for(image)
      end,
    )
  end

  def create
    # The `Post` model should be defined or required in this file.
    @post = Post.new(post_params.except(:images))

    # The `save` method should be called after images have been attached.
    if @post.save
      images = params[:post][:images]

      if images
        images.each do |image|
          @post.images.attach(image)
        end
      end

      render json: @post, status: :created, location: @post
    else
      render json: @post.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /posts/1
  def update
    if @post.update(post_params)
      render json: @post
    else
      render json: @post.errors, status: :unprocessable_entity
    end
  end

  # DELETE /posts/1
  def destroy
    @post.destroy
  end

  private

  # Use callbacks to share common setup or constraints between actions.
  def set_post
    @post = Post.find(params[:id])
  end

  # Only allow a list of trusted parameters through.
  def post_params
    params.require(:post).permit(images: [])
  end
end

```

The `show` action will return a `JSON response` of a specific post and its images. The `as_json` method is used to include the associated images with the post, and the merge method is used to add a new key-value pair images in the response JSON that contains an array of image URLs.


The `create` action creates a new post and attaches any images that were passed in the request parameters. The `except` method is used to remove the images parameter from the post_params hash, as it is handled separately in the images variable. The `permit` method is used to allow an array of image attachments to be passed in the request parameters.


The `update` action updates an existing post with the new parameters passed in the request. The `save` method is used to update the post with the new parameters, and the post_params method is passed in as an argument.


The `destroy` action deletes a specific post.


The `set_post` method is a private method that finds the post with the specified ID and assigns it to the instance variable @post. 

The `before_action` method is used to call this method before the show, update, and destroy actions are executed.


- Now we Confugure the database and make sure that the `database.yml` file under `config/` directory looks like the following

```yml
default: &default
  adapter: postgresql
  encoding: unicode
  username: postgres
  password: 123456
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: multiple_image_uploads_development

  <<: *default
  database: multiple_image_uploads_test

production:
  <<: *default
  database: multiple_image_uploads_production
  username: multiple_image_uploads
  password: <%= ENV["MULTIPLE_IMAGE_UPLOADS_DATABASE_PASSWORD"] %>
```

You can replace the `username` and `password` by you postgres host configuration

- Create the database and run migrations

```sh
rails db:create db:migrate
```

- Now run the rails server
```sh
rails server
```


The database.yml file under the config/ directory sets the default adapter to PostgreSQL, specifies the database encoding as Unicode, and sets the default pool size to 5 threads. The development and test environments use the same database configuration as the default, while the production environment uses a different database name and a custom username and password.


The `rails db:create` command creates the databases specified in the database.yml file, and the `rails db:migrate` command runs any pending migrations to update the database schema.


Finally, the `rails server` command starts the Rails server, which listens for incoming requests on [localhost:3000](http://127.0.0.1:3000/posts) by default. With the database configured and the server running, the Rails application is ready to receive and respond to requests.


_Overall, this code sets up a RESTful API for posts with image attachments, allowing clients to create, read, update, and delete posts with images._

## **[⏮⏮ intro](https://dev.to/chrissiku/upload-multiple-images-to-rails-7-api-activestorage-intro-14l2) ________________________ [part 2⏭⏭](https://dev.to/chrissiku/upload-multiple-images-to-rails-7-api-activestorage-part-2-4dll)**