railsでactive_hashを導入する

railsのアプリを作っていて、絶対に変動がないデータなどを保存しておくのにいちいちデータベース作って置いておくの面倒だなと思い、検索して出てきました。
使ってみたところなかなかの使い勝手だったので、簡単にactive_hashを導入できる記事を書いてみようと思います。

スポンサーリンク

目的

active_hashを導入

(前提、環境)

mac
macOS Mojave 10.14.5
ruby 2.5.1
rails 5.2.3

はじめに

公式

まずは公式のgithubを確認しましょう。

zilkey/active_hash
https://github.com/zilkey/active_hash

active_hashとは

Active_Recordのように読み込み専用情報をまとめたハッシュを扱うことができるものです。
もし、現在アプリのデータベースに例えば都道府県だったり変動が起きないものデータを保存している場合、すぐ入れ替えることができます。

導入

gem ‘active_hash’をインストール

アプリのGemfileに以下を記述

gem 'active_hash'

注意

最新のversionは3.0.0(2019年12月現在)だけど、アプリを壊す可能性があるので、壊れたら下記の記事を見て、2.3.0にしてください!。

壊れた時の対処方法
https://github.com/zilkey/active_hash/issues

gem 'active_hash', '~> 2.3.0'

使っているRubyのversionが2.4未満・Railsのversionが5未満の時は以下でやってくださいね!

gem 'active_hash', '~> 1.5.3'

使用方法

初期設定

重要なことは2つです。
①Active_Hash::Baseを継承しているモデルを作成する。
②データを用意する。

①Active_Hash::Baseを継承しているモデルを作成する。

今回はgithubを参考にPrefectureモデルを作っていきます。

# in app/models/prefecture.rb
class Prefecture < ActiveHash::Base
end

②データを用意する。

データをセットする方法は4つあります。

  • config/initializers/data.rbというファイルを作成してセット
  • モデル内に配列形式で書く
  • モデル内にfield :name形式で書く
  • モデル内にyml形式で書く

モデルにたくさん情報を載せるのが嫌だという人もいると思うので、
config/initializers/data.rbというファイルを作成して入れておく方法がオススメです!

# config/initializers/data.rb
Rails.application.config.to_prepare do
  Prefecture.data = [
      {:id => 1, :name => "北海道"},
      {:id => 2, :name => "青森県"}
  ]
end

以下お勧めではないですが例を載せておきます。

# in app/models/prefecture.rb
class Prefecture < ActiveHash::Base
  self.data = [
    {:id => 1, :name => "北海道"},
    {:id => 2, :name => "青森県"}
  ]
end
# in app/models/prefecture.rb
class Prefecture < ActiveHash::Base
  field :name
  create :id => 1, :name => "北海道"
  create :id => 2, :name => "青森県"
end
# in app/models/prefecture.rb
class Prefecture < ActiveHash::Base
  field :name
  add :id => 1, :name => "北海道"
  add :id => 2, :name => "青森県"
end

コンソールで検証

まずは以下のコマンドをRailのアプリのディレクトリで打って確認してみます。

bundle exec rails c
tests = Prefecture.all
=> #<ActiveHash::Relation:0x00007ff418959b10
 @all_records=
  [#<Prefecture:0x00007ff41895a380 @attributes={:id=>1, :name=>"北海道"}>,
   #<Prefecture:0x00007ff41895a088 @attributes={:id=>2, :name=>"青森県"}>],
 @klass=Prefecture,
 @query_hash={},
 @records_dirty=false>

ActiveHash::Relationモジュールのインスタンスらしく、このままtest[0]とかで打ってもデータが取れなかったので.all_recordsメソッドでチェーンします。

tests.all_records
=> [#<Prefecture:0x00007ff41895a380 @attributes={:id=>1, :name=>"北海道"}>,
 #<Prefecture:0x00007ff41895a088 @attributes={:id=>2, :name=>"青森県"}>]

tests.all_records[0].name
=> "北海道"

Active_Recordのモデルとのアソシエーション

今回は例としてPrefectureとUserが1対他の関係を定義します。
※usersテーブルにはprefecture_idを作成しておきます。

active_hash側のモデルに定義すること

モデル内にinclude ActiveHash::Associationsを記述します。

class Prefecture < ActiveHash::Base
  include ActiveHash::Associations
  has_many :users
end

Active_Recordのモデル側に定義すること

モデル内に extend ActiveHash::Associations::ActiveRecordExtensionsを記述します。

class Person < ActiveRecord::Base
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :prefecture
end

コンソールで検証

まずは以下のコマンドをRailのアプリのディレクトリで打って確認してみます。

bundle exec rails c
sample_user = User.new(prefecture_id: 1)
=> #<User id: nil, created_at: nil, updated_at: nil, prefecture_id: 1>

sample_user.save
sample_user.prefecture
=> #<Prefecture:0x00007f8ca5b5d090 @attributes={:id=>1, :name=>"北海道"}>
sample_user.prefecture.name
=> "北海道"

結果

導入にあたってデータベースを作ってseedを走らせなくていいし、保持しておく必要がないのでとても楽ですね!!
非常に管理も楽です笑

参考になれば是非!!

番外編 〜使えるメソッド一覧〜

Active_Recordと同じようなメソッド一覧が使えます。
いつもと変わらない使用感。
(こちらはgithubからそのまま抜粋)

クラスメソッド一覧

Country.all                    # => returns all Country objects
Country.count                  # => returns the length of the .data array
Country.first                  # => returns the first country object
Country.last                   # => returns the last country object
Country.find 1                 # => returns the first country object with that id
Country.find [1,2]             # => returns all Country objects with ids in the array
Country.find :all              # => same as .all
Country.find :all, args        # => the second argument is totally ignored, but allows it to play nicely with AR
Country.find { |country| country.name.start_with?('U') } # => returns the first country for which the block evaluates to true
Country.find_by_id 1           # => find the first object that matches the id
Country.find_by(name: 'US')    # => returns the first country object with specified argument
Country.find_by!(name: 'US')   # => same as find_by, but raise exception when not found
Country.where(name: 'US')      # => returns all records with name: 'US'
Country.where.not(name: 'US')  # => returns all records without name: 'US'
Country.order(name: :desc)     # => returns all records ordered by name attribute in DESC order

インスタンスメソッド一覧

Country#id          # => returns the id or nil
Country#id=         # => sets the id attribute
Country#quoted_id   # => returns the numeric id
Country#to_param    # => returns the id as a string
Country#new_record? # => returns true if is not part of Country.all, false otherwise
Country#readonly?   # => true
Country#hash        # => the hash of the id (or the hash of nil)
Country#eql?        # => compares type and id, returns false if id is nil

終わりに

Railsエンジニアになるためのロードマップをご紹介!

未経験者から最強のRailsエンジニアになるためのロードマップ
webアプリエンジニアになるためにどの程度学習すべきかをまとめた記事です。
タイトルとURLをコピーしました