LoginSignup
0
0

More than 1 year has passed since last update.

[Rails6]ActiveHashについて 〜変更されないデータの取扱い方〜

Posted at

はじめに

現在未経験からのエンジニアへの転職するため、日々学習を励んでいます。  
知識整理のためアウトプットします!  
間違った内容などあるかもしれませんがご容赦ください!

ActiveHashとは

一言でまとめると、「変更されないデータをデータベースに保存することなく取り扱うことができるgem」と理解してます!
例えば、都道府県一覧などは変更されないですよね?!  
このようなデータを直接モデルに記入することで、データベースには保存せずともデータが取り扱えるgemです!
つまり、ActiveHashを用いることでActiverecordメソッドが使えるようになるんです!

導入方法

gemfile
gem 'active_hash'
ターミナル
%  bundle install

これで下準備は終わり。

モデルを作成する

今回は、料理投稿アプリを想定して、foodモデルと、costモデルを作成します。

マイグレーションファイル(foodsテーブル)
class CreateFoods < ActiveRecord::Migration[6.0]
  def change
    create_table :foods do |t|
      t.string :title,    null: false
      t.integer :cost_id, null: false
      t.timestamps
    end
  end
end

ここで注意!
カラム名に_idをつけ、カラムの型はinteger型にしましょう!  

cost.rb
class Cost < ActiveHash::Base
  self.data = [
    { id: 1, name: '100円以下' },
    { id: 2, name: '300円前後' },
    { id: 3, name: '500円前後' },
    { id: 4, name: '1,000円前後' },
    { id: 5, name: '2,000円前後' },
    { id: 6, name: '3,000円前後' },
    { id: 7, name: '5,000円前後' },
    { id: 8, name: '10,000円前後' },
  ]
end

cost.rbはエディタから直接ファイルを作り上記の方に記述します。

まずは、モデルの「Costクラス」を定義し、ActiveHash::Baseクラスを継承します。
ActiveHash::Baseは、あるクラス内でActiveHashを用いる際に必要となるクラスです。
ActiveHash::Baseを継承することで、ActiveRecordメソッドを使用できるようになります。

アソシエーションの設定

投稿した料理は、1つのコストに紐付いています。そのため、Foodモデルにはbelongs_toを設定します。
この際、extend ActiveHash::Associations::ActiveRecordExtensionsと記述してmoduleを取り込みます。

food.rb
class Food < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :cost
end

1つのコストは、たくさんの投稿した料理に紐付いています。そのため、Genreモデルにはhas_manyを設定します。
この際、include ActiveHash::Associationsと記述してmoduleを取り込みます。

cost.rb
class Cost < ActiveHash::Base
  self.data = [
    { id: 1, name: '100円以下' },
    { id: 2, name: '300円前後' },
    { id: 3, name: '500円前後' },
    { id: 4, name: '1,000円前後' },
    { id: 5, name: '2,000円前後' },
    { id: 6, name: '3,000円前後' },
    { id: 7, name: '5,000円前後' },
    { id: 8, name: '10,000円前後' },
  ]

include ActiveHash::Associations #ここを追加
has_many :foods #ここを追加

end

collection_selectを用いてブルダウンメニューを表示させる。

○○○.html.erb
<%= f.collection_select(:cost_id, Cost.all, :id, :name, {}, {class:"cost-select"}) %>

#各引数の役割
<%= form.collection_select(保存されるカラム名, オブジェクトの配列, カラムに保存される項目, 選択肢に表示されるカラム名, オプション, htmlオプション) %>

バリデーションを設定しよう

今回は2パターン紹介します!

①「numericality」というバリデーション のヘルパーを使用する方法

numericalityとは、数値かどうかを検証するバリデーションの一種です。
数値であればデータベースに保存を許可して、それ以外では保存が許可されないようにできます。

cost.rb
class Cost < ActiveHash::Base
  self.data = [
    { id: 1, name: '---' }, #id:1に「---」を追加する。
    { id: 2, name: '100円以下' },
    { id: 3, name: '300円前後' },
    { id: 4, name: '500円前後' },
    { id: 5, name: '1,000円前後' },
    { id: 6, name: '2,000円前後' },
    { id: 7, name: '3,000円前後' },
    { id: 8, name: '5,000円前後' },
    { id: 9, name: '10,000円前後' },
  ]

include ActiveHash::Associations
has_many :foods

end
food.rb
class Food < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :cost

  validates :title, presence: true

  #コストの選択が「---」の時は保存できないようにする
  validates :cost_id, numericality: { other_than: 1 } 
end

②collection_selectのオプションを使用する方法

collection_selectの第五引数で設定するオプションを使用します。

○○○.html.erb
#第五引数に{ include_blank: "---" }を記入する。
<%= f.collection_select(:cost_id, Cost.all, :id, :name, { include_blank: "---" }, {class:"cost-select"}) %>

include_blankをしようすることで、値のない選択肢を先頭にすることができます。
そうすることで、、、with_optionsでまとめることができる!!
ちょっと見やすいかな?

food.rb
class Food < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :cost

  with_options presence: true do
    validates :title
    validates :cost_id
  end
end

終わりに

以上になります!
間違ってたら、バシバシ言っていただけるとありがたいです!

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0