Generate QR-code with Active Storage in Ruby on Rails 7
Tags: rails, qrcode, ruby, webdev
Published: 2023-03-01 21:23:56



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ad59egg6wdny6e1oljck.PNG)

QR codes are an essential part of modern technology. They allow us to easily transfer information from one device to another. In this blog post, we will explore how to generate a QR code with Ruby on Rails using Active Storage and the gem "rqrcode."

Before we begin, let's make sure we have everything we need. 

### Create a new rails project named qr-code
```sh
rails new qr-code
```

### Add the [rqrcode](https://github.com/whomwah/rqrcode) gem to the gem file by running the command below :
```sh
bundle add rqrcode
```
### Generate a scaffold for a Post model
```sh
rails g scaffold post title body:text
```

This command generates several files that make it easy to quickly create a functional CRUD (Create, Read, Update, Delete) interface for managing Posts in our web application.

Here's what each part of the command does:

- `rails` is the command to run Ruby on Rails.
- `g` is short for "generate."
- `scaffold` tells Rails to generate a complete set of files for a model, including a controller, views, and a migration.
- `post` is the name of the model we want to generate.
- `title` and `body:text` are attributes of the Post model. "title" is a string attribute, and "body" is a text attribute.

By generating a scaffold, we can quickly create a functional interface for managing Posts in our Rails application, saving time and effort. However, it's important to note that the generated code may not be perfect for our specific needs, and we may need to modify it to fit our requirements

### Now let's install [active_storage](https://guides.rubyonrails.org/active_storage_overview.html):
run the command bellow :
```sh
rails active_storage:install
```
The is command is used to install and set up Active Storage in a Ruby on Rails application. [Active Storage](https://guides.rubyonrails.org/active_storage_overview.html) is a built-in framework for managing file uploads and attachments in Rails applications.

At this point of the project, we can now create our database, migrate all tables.

```sh
rails db:create
rails db:migrate
```
Before running the server, we need to set the default URL options for the Rails action controller by specifying the host and port that the application should be running on. 

To do so add the following line to your `development.rb` file under `config/environments/`
```ruby
# config/environments/development.rb
config.action_controller.default_url_options = { host: "localhost:3000", port: 3000 }

```

The begining of your file should look like in the following code snippet

```ruby
# config/environments/development.rb
require "active_support/core_ext/integer/time"

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.
  config.action_controller.default_url_options = { host: "localhost:3000", port: 3000 }

  # In the development environment your application's code is reloaded any time
  # it changes. This slows down response time but is perfect for development

# [... more code below ...]
end
```

Now you can start the application server by running the command bellow:
```sh
rails server
```
Now open your browser and navigate to [http://localhost:3000](http://localhost:3000/), you should see the interface below 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z8kndx8tqqoz03tqxjdh.PNG)

_If you can see the above interface in your browser, that means you are ready to start, if not, you can go back and follow all the steps for better understanding._ ♻♻


- As we have everything working, open you `routes.rb` file under `/config/` directore and set the root path for the application: 

```ruby
# config/routes.rb
Rails.application.routes.draw do
  root "posts#index"
  resources :posts
end
```
### Go to `app/models/post.rb` and add the attach the `qrcode` to the post model

```ruby
# app/models/post.rb
class Post < ApplicationRecord
  has_one_attached :qrcode, dependent: :destroy
end
```

The code above Ruby on Rails ActiveRecord association method that defines a **one-to-one attachment** association for our post model.

The **has_one_attached** method is provided by the Active Storage library, and it enables attaching a single file to the post model. This attachment is stored in a separate table in the database, and the association is handled by Active Storage.

- **👌 Good to know 👌**: _Overall, this code allows you to attach a single file to the post model, and ensures that the attachment is properly managed and cleaned up when needed. This is useful for cases where you need to store and manage file attachments within your Rails application._

### Add the `:qrcode` in the strong parameters method (post_params) used to whitelist and filter the parameters passed to a create action.

- Go to `app\controllers\posts_controller.rb` and make sure it looks like the following : 

```ruby
class PostsController < ApplicationController
# app\controllers\posts_controller.rb

# [ ... ]

  # Only allow a list of trusted parameters through.
  def post_params
    params.require(:post).permit(:title, :body, :qrcode)
  end
end
```

### Implement the before_commit in the **Post** model
- Follow the [rqrcode] gem(https://github.com/whomwah/rqrcode) documentation to set everthing and after make sure that your `post.rb` file under `app/models/` looks like the following :

```ruby
# app/models/posts.rb
class Post < ApplicationRecord
  include Rails.application.routes.url_helpers
  has_one_attached :qrcode, dependent: :destroy

  before_commit :generate_qrcode, on: :create

  private

  def generate_qrcode
    # Get the host
    # host = Rails.application.routes.default_url_options[:host]
    host = Rails.application.config.action_controller.default_url_options[:host]

    # Create the QR code object
    # qrcode = RQRCode::QRCode.new("http://#{host}/posts/#{id}")
    qrcode = RQRCode::QRCode.new(post_url(self, host:))

    # Create a new PNG object
    png = qrcode.as_png(
      bit_depth: 1,
      border_modules: 4,
      color_mode: ChunkyPNG::COLOR_GRAYSCALE,
      color: "black",
      file: nil,
      fill: "white",
      module_px_size: 6,
      resize_exactly_to: false,
      resize_gte_to: false,
      size: 120,
    )

    # Attach the QR code to the active storage
    self.qrcode.attach(
      io: StringIO.new(png.to_s),
      filename: "qrcode.png",
      content_type: "image/png",
    )
  end
end
```

For the above code snippet I define a **generate_qrcode** method that generates a QR code for the post and attaches it to the qrcode association using Active Storage.

Here's a brief summary of what the code does:

#### The Post model 
  - Includes the **Rails.application.routes.url_helpers** module, which provides helper methods for generating URLs in Rails.

#### The `before_commit :generate_qrcode, on: :create` callback 
  - Runs the **generate_qrcode** method before the post is committed to the database on creation.

#### The `generate_qrcode` method    

1. Generates a QR code for the post and attaches it to the qrcode association using Active Storage.

2. Uses the **Rails.application.config.action_controller.default_url_options[:host]** configuration value to get the host name for the current Rails application.

3. Generates a QR code using the **RQRCode::QRCode.new** method, passing in the post's URL as a string.

4. Uses the **qrcode.as_png** method to generate a PNG image of the QR code.

5. Attaches the QR code image to the qrcode association using Active Storage.


**👌Good to know👌**: _Overall, this code generates a QR code image for a new post and attaches it to the post using Active Storage. The QR code can then be used to link to the post's URL, making it easy to share the post with others._

You can copy the above code and ajust it to your.

### Here we go,
- As now we have generated our qr-code, let's display it on the post page.

Open the `_post.html.erb` partial file under `app/views/posts/` and add an image_tag for the qrcode as follow :

```ruby
# app/views/posts/_post.html.erb
<div id="<%= dom_id post %>">
  <p>
    <strong>Title:</strong>
    <%= post.title %>
  </p>

  <p>
    <strong>Body:</strong>
    <%= post.body %>
  </p>

  <%= image_tag(url_for(post.qrcode)) %>
</div>
```
- Now save you project and create a new post on the browser.
After creation you should see the qr-code displayed on the web page as the one on the image bellow :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1valid5nrkh17eo2tze.PNG)


Now you might need to test that qr-code.
   - There are several ways to test this and from your browser just 
open the site [webqr](https://webqr.com/) and make sure your camera is filming your screen.

   -  Or just use the qr-code reader of your phone.

**In conclusion**, generating QR codes is now an essential part of modern technology as it allows us to easily transfer information from one device to another. 

In this blog post, we have learned how to generate a QR code with Ruby on Rails using Active Storage and the [gem "rqrcode"](https://github.com/whomwah/rqrcode). By following the step-by-step guide provided in the post, we were able to create a functional CRUD interface for managing Posts in our web application, and also learned how to install and set up [Active Storage](https://guides.rubyonrails.org/active_storage_overview.html) in a Ruby on Rails application. 

Finally, we attached a qrcode to our post model using Ruby on Rails **ActiveRecord association** method, added the :qrcode in the strong parameters method (post_params), and whitelisted and filtered the parameters passed to a create action. 

### Github : [qrcode-generator](https://github.com/Chrissiku/qrcode-generator)
### Documentation : [rqrcode](https://github.com/whomwah/rqrcode)

_Overall, this post provides an excellent guide for anyone looking to generate QR codes using Ruby on Rails._