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.
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.
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.
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
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 %>
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>
Recommended Posts