[RUBY] Introduction purpose of ActiveHash and simple flow to application implementation

What is Active Hash?

It is a gem that can handle data without saving it in the database by ** describing the unchanged data such as the prefecture name directly in the model file **.

With ActiveHash, it's a great help when creating pull-down menus like the one below.

スクリーンショット 2021-01-16 23.55.35.png

Purpose of introducing ActiveHash

Unlike data that may be edited, such as user information, prefecture names are unchanged data, so there is no need to save them in a database.

However, if you create a pull-down menu of prefecture names directly in the view file, the code will become bloated and readability will decrease.

Therefore, it is easier to manage the code by using ActiveHash to call the data from the model.

Implementation of pull-down menu

I will explain using the app that posts the prefecture where you live.

Enter the following command to create a Rails app.

Terminal


rails _6.0.0_ new activehash_app -d mysql
rails db:create

Next, prepare the model, controller, and view.

Create a model

Terminal


rails g model address      

Write the name column and prefecture_id column in the migration file generated by the above command as follows and migrate.

The prefecture_id column contains information about pull-down menus that will be introduced later in the ActiveHash gem.

The data type is integer type because the data of prefecture to be created later is quoted from id like an association.

2021XXXXXXXXXX_create_addresses.rb


class CreateAddresses < ActiveRecord::Migration[6.0]
  def change
    create_table :addresses do |t|
      t.string :name, null: false
      t.integer :prefecture_id, null: false
      t.timestamps
    end
  end
end

Terminal


rails db:migrate

Create controller and view

In addition to the controller, use the following command to create a list view and a view of new posts together.

Terminal


rails g controller addresses index new

Write the controller and view (index and new) as follows:

app/controllers/addresses_controller.rb


class AddressesController < ApplicationController
  def index
    @addresses = Address.order("created_at DESC")
  end

  def new
    @address = Address.new
  end

  def create
    @address = Address.new(address_params)
    if @address.valid?
      @address.save
      return redirect_to root_path
    else
      render "new"
    end
  end

  private
  def address_params
    params.require(:address).permit(:name, :prefecture_id)
  end
end

html:app/views/addresses/index.html.erb


<h1>What prefecture do you live in?</h1>
<%= link_to "Post", new_address_path %>
<div>
  <ul>
    <% if @addresses %>
      <% @addresses.each do |address| %>
      <li>
        <%= address.name %>
        <%= address.prefecture.name %>
      </li>
      <% end %>
    <% end %>
  </ul>
</div>

erb:app/views/addresses/new.html.erb


<%= form_with model: @address, url:addresses_path, local: true do |f| %>
  <div class="article-box">
Post your name and the prefecture you live in
    <div>
      <p><%= f.text_area :name, placeholder:"Your name" %></p>
      <p><%= f.collection_select(:prefecture_id, Prefecture.all, :id, :name, {}, {class:"genre-select"}) %></p>
      <%= f.submit "Post" ,class:"btn" %>
    </div> 
  </div>
  <%= link_to "Return", root_path %>
<% end %>

Introduction of ActiveHash

We are finally introducing Active Hash. Write the following at the bottom of Gemfile and bundle install in the terminal.

Gemfile


gem 'active_hash'

Terminal


bundle install

Create a prefecture model to prepare a list of prefectures.

Now add the option --skip-migration to the usual rails g model: model name command.

--skip-migration is an option that skips the creation of migration files. This is because information about prefectures is not stored in the database.

Terminal


rails g model prefecture --skip-migration

In the created prefecture.rb, describe as follows.

app/models/prefecture.rb


class Prefecture < ActiveHash::Base
  self.data = [
    {id: 0, name: '--'}, {id: 1, name: 'Hokkaido'}, {id: 2, name: 'Aomori Prefecture'}, 
    {id: 3, name: 'Iwate Prefecture'}, {id: 4, name: 'Miyagi Prefecture'}, {id: 5, name: 'Akita'}, 
    {id: 6, name: 'Yamagata Prefecture'}, {id: 7, name: 'Fukushima Prefecture'}, {id: 8, name: 'Ibaraki Prefecture'}, 
    {id: 9, name: 'Tochigi Prefecture'}, {id: 10, name: 'Gunma Prefecture'}, {id: 11, name: 'Saitama'}, 
    {id: 12, name: 'Chiba'}, {id: 13, name: 'Tokyo'}, {id: 14, name: 'Kanagawa Prefecture'}, 
    {id: 15, name: 'Niigata Prefecture'}, {id: 16, name: 'Toyama Prefecture'}, {id: 17, name: 'Ishikawa Prefecture'}, 
    {id: 18, name: 'Fukui prefecture'}, {id: 19, name: 'Yamanashi Prefecture'}, {id: 20, name: 'Nagano Prefecture'}, 
    {id: 21, name: 'Gifu Prefecture'}, {id: 22, name: 'Shizuoka Prefecture'}, {id: 23, name: 'Aichi prefecture'}, 
    {id: 24, name: 'Mie Prefecture'}, {id: 25, name: 'Shiga Prefecture'}, {id: 26, name: 'Kyoto'}, 
    {id: 27, name: 'Osaka'}, {id: 28, name: 'Hyogo prefecture'}, {id: 29, name: 'Nara Prefecture'}, 
    {id: 30, name: 'Wakayama Prefecture'}, {id: 31, name: 'Tottori prefecture'}, {id: 32, name: 'Shimane Prefecture'}, 
    {id: 33, name: 'Okayama Prefecture'}, {id: 34, name: 'Hiroshima Prefecture'}, {id: 35, name: 'Yamaguchi Prefecture'}, 
    {id: 36, name: 'Tokushima Prefecture'}, {id: 37, name: 'Kagawa Prefecture'}, {id: 38, name: 'Ehime Prefecture'}, 
    {id: 39, name: 'Kochi Prefecture'}, {id: 40, name: 'Fukuoka Prefecture'}, {id: 41, name: 'Saga Prefecture'}, 
    {id: 42, name: 'Nagasaki Prefecture'}, {id: 43, name: 'Kumamoto Prefecture'}, {id: 44, name: 'Oita Prefecture'}, 
    {id: 45, name: 'Miyazaki prefecture'}, {id: 46, name: 'Kagoshima prefecture'}, {id: 47, name: 'Okinawa Prefecture'}
  ]
  include ActiveHash::Associations #Load the module defined in ActiveHash
  has_many :address #Define an association with the address model
end

Put the data of prefectures in the array in hash format. Also, include ActiveHash :: Associations loads the module defined in ActiveHash and describes has_many to define the association with the Address model.

See the official GitHub README (https://github.com/zilkey/active_hash) and Library (https://github.com/zilkey/active_hash/tree/master/lib) for ActiveHash modules.

Similarly, load the module in address.rb and define the association with the Prefecture model with belongs_to.

app/models/address.rb


class Address < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions #Load the module defined in Activehash
  belongs_to :prefecture #Define association with prefecture model
end

By defining the above association, you can now access the prefecture name stored in the Prefecture model with the index.html.erb created earlier.

erb:app/views/addresses/index.html.erb (repost)


<h1>What prefecture do you live in?</h1>
<%= link_to "Post", new_address_path %>
<div>
  <ul>
    <% if @addresses %>
      <% @addresses.each do |address| %>
      <li>
        <%= address.name %>
        <%= address.prefecture.name %><%#Prefecure by association definition.You can access the prefecture name stored in rb%>
      </li>
      <% end %>
    <% end %>
  </ul>
</div>

Reference material

Active Hash Official GitHub

Recommended Posts

Introduction purpose of ActiveHash and simple flow to application implementation
From introduction to use of ActiveHash
Introduction of Sudoku answer application "Sudoku automatic answer" (Android version) and its implementation function
Introduction and basic usage of Simple Calendar gem
[Swift] Simple implementation of UIImageView
Introduction to Android application development
From introduction to usage of byebug
Default implementation of Object.equals () and Object.hashCode ()
Application of downcase and slice methods
[Java] Flow from introduction of STS to confirmation of dynamic page on localhost (2/3)
[Java] Flow from introduction of STS to confirmation of dynamic page on localhost (1/3)
Confirmation and refactoring of the flow from request to controller in [httpclient]
[Java] Note how to use RecyclerView and implementation of animated swipe processing.
[Rails] Articles for beginners to organize and understand the flow of form_with
Whereabouts of JAXB Reference implementation and DatatypeConverterImpl
Java implementation to create and solve mazes
Personal application production 2 Introduction of WEB fonts
Introduction to EHRbase 1-Overview and Environmental Improvement
Implementation of tabs using TabLayout and ViewPager
Output of the book "Introduction to Java"
Introduction and precautions of gem Friendly Id
[Introduction to Java] Variable declarations and types
Introduction and usage explanation of Font Awesome
[Vue.js] Implementation of menu function Vue.js introduction rails6
Summary of good points and precautions when converting Java Android application to Kotlin
Basics of Java development ~ How to write a program (flow and conditional branching) ~