SlideShare a Scribd company logo
1 of 21
Download to read offline
Implementation of EAV
        pattern for ActiveRecord
                 models


Kostyantyn Stepanyuk   kostya.stepanyuk@gmail.com   https://github.com/kostyantyn
Entity - Attribute - Value
Schema
Entity Type
Attribute Set
ActiveRecord and EAV
https://github.com/kostyantyn/example_active_record_as_eav
Specification


1. Save Entity Type as string in Entity Table (STI pattern)
2. Keep attributes directly in the model
3. Use Polymorphic Association between Entity and Value
Migration

class CreateEntityAndValues < ActiveRecord::Migration
  def change
    create_table :products do |t|
      t.string :type
      t.string :name
      t.timestamps
    end

    %w(string integer float boolean).each do |type|
      create_table "#{type}_attributes" do |t|
        t.references :entity, polymorphic: true
        t.string :name
        t.send type, :value
        t.timestamps
      end
    end
  end
end
Attribute Models

class Attribute < ActiveRecord::Base
  self.abstract_class = true
  attr_accessible :name, :value
  belongs_to :entity, polymorphic: true, touch: true, autosave: true
end

class BooleanAttribute < Attribute
end

class FloatAttribute < Attribute
end

class IntegerAttribute < Attribute
end

class StringAttribute < Attribute
end
Product

class Product < ActiveRecord::Base
  %w(string integer float boolean).each do |type|
    has_many :"#{type}_attributes", as: :entity, autosave: true, dependent: :delete_all
  end

  def eav_attr_model(name, type)
    attributes = send("#{type}_attributes")
    attributes.detect { |attr| attr.name == name } || attributes.build(name: name)
  end

  class << self
    def eav(name, type)
      class_eval <<-EOS, __FILE__, __LINE__ + 1
        attr_accessible :#{name}
        def #{name};        eav_attr_model('#{name}', '#{type}').value         end
        def #{name}=(value) eav_attr_model('#{name}', '#{type}').value = value end
        def #{name}?;       eav_attr_model('#{name}', '#{type}').value?        end
      EOS
    end
  end
end
Simple Product

class SimpleProduct < Product
  attr_accessible :name

  eav   :code,       :string
  eav   :price,      :float
  eav   :quantity,   :integer
  eav   :active,     :boolean
end
Advanced Attribute Methods

class Product < ActiveRecord::Base
  def self.eav(name, type)
    attr_accessor name

    attribute_method_matchers.each do |matcher|
      class_eval <<-EOS, __FILE__, __LINE__ + 1
        def #{matcher.method_name(name)}(*args)
          eav_attr_model('#{name}', '#{type}').send :#{matcher.method_name('value')}, *args
        end
      EOS
    end
  end
end
Usage

SimpleProduct.create(code: '#1', price: 2.75, quantity: 5, active: true).id
# 1

product = SimpleProduct.find(1)
product.code     # "#1"
product.price    # 2.75
product.quantity # 5
product.active? # true

product.code_changed? # false
product.code = 3.50
product.code_changed? # true
product.code_was      # 2.75

SimpleProduct.instance_methods.first(10)
# [:code, :code=, :code_before_type_cast, :code?, :code_changed?, :
code_change, :code_will_change!, :code_was, :reset_code!, :_code]
What about query methods?

class Product < ActiveRecord::Base
  def self.scoped(options = nil)
    super(options).extend(QueryMethods)
  end

 module QueryMethods
   def select(*args, &block)
     super(*args, &block)
   end

   def order(*args)
     super(*args)
   end

    def where(*args)
      super(*args)
    end
  end
end
hydra_attribute
https://github.com/kostyantyn/hydra_attribute
Installation

class Product < ActiveRecord::Base
  attr_accessor :title, :code, :quantity, :price, :active, :description
  define_hydra_attributes do
    string :title, :code
    integer :quantity
    float   :price
    boolean :active
    text    :description
  end
end

class GenerateAttributes < ActiveRecord::Migration
  def up
    HydraAttribute::Migration.new(self).migrate
  end

  def down
    HydraAttribute::Migration.new(self).rollback
  end
end
Helper Methods

Product.hydra_attributes
# [{'code' => :string, 'price' => :float, 'quantity' => :integer, 'active'
=> :boolean}]

Product.hydra_attribute_names
# ['code', 'price', 'quantity', 'active']

Product.hydra_attribute_types
# [:string, :float, :integer, :boolean]

Product.new.attributes
# [{'name' => nil, 'code' => nil, 'price' => nil, 'quantity' => nil,
'active' => nil}]

Product.new.hydra_attributes
# [{'code' => nil, 'price' => nil, 'quantity' => nil, 'active' => nil}]
Where Condition

Product.create(price: 2.50) # id: 1
Product.create(price: nil) # id: 2
Product.create              # id: 3

Product.where(price: 2.50).map(&:id) # [1]
Product.where(price: nil).map(&:id) # [2, 3]
Select Attributes

Product.create(price: 2.50) # id: 1
Product.create(price: nil) # id: 2
Product.create              # id: 3

Product.select(:price).map(&:attributes)
# [{'price' => 2.50}, {'price => nil}, {'price' => nil}]

Product.select(:price).map(&:code)
# ActiveModel::MissingAttributeError: missing attribute: code
Order and Reverse Order

Product.create(title: 'a') # id: 1
Product.create(title: 'b') # id: 2
Product.create(title: 'c') # id: 3

Product.order(:title).first.id                 # 1
Product.order(:title).reverse_order.first.id   # 3
Questions?

More Related Content

What's hot

ストリーム処理におけるApache Avroの活用について(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)
ストリーム処理におけるApache Avroの活用について(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)ストリーム処理におけるApache Avroの活用について(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)
ストリーム処理におけるApache Avroの活用について(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)NTT DATA Technology & Innovation
 
事例から見る規模別クラウド・データベースの選び方 (Oracle Database) (Oracle Cloudウェビナーシリーズ: 2021年6月30日)
事例から見る規模別クラウド・データベースの選び方 (Oracle Database) (Oracle Cloudウェビナーシリーズ: 2021年6月30日)事例から見る規模別クラウド・データベースの選び方 (Oracle Database) (Oracle Cloudウェビナーシリーズ: 2021年6月30日)
事例から見る規模別クラウド・データベースの選び方 (Oracle Database) (Oracle Cloudウェビナーシリーズ: 2021年6月30日)オラクルエンジニア通信
 
Understanding PostgreSQL LW Locks
Understanding PostgreSQL LW LocksUnderstanding PostgreSQL LW Locks
Understanding PostgreSQL LW LocksJignesh Shah
 
InfiniFlux vs influxdb 비교 테스트 결과 2016 12월-v2
InfiniFlux vs influxdb 비교 테스트 결과 2016 12월-v2InfiniFlux vs influxdb 비교 테스트 결과 2016 12월-v2
InfiniFlux vs influxdb 비교 테스트 결과 2016 12월-v2Andrew Sungjin Kim
 
Oracle Cloud PaaS & IaaS:2019年11月度サービス情報アップデート
Oracle Cloud PaaS & IaaS:2019年11月度サービス情報アップデートOracle Cloud PaaS & IaaS:2019年11月度サービス情報アップデート
Oracle Cloud PaaS & IaaS:2019年11月度サービス情報アップデートオラクルエンジニア通信
 
OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)
OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)
OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)NTT DATA Technology & Innovation
 
第一次Elasticsearch就上手
第一次Elasticsearch就上手第一次Elasticsearch就上手
第一次Elasticsearch就上手Aaron King
 
ASP.NET MVC Performance
ASP.NET MVC PerformanceASP.NET MVC Performance
ASP.NET MVC Performancerudib
 
Caching ガイダンスの話
Caching ガイダンスの話Caching ガイダンスの話
Caching ガイダンスの話Sunao Tomita
 
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Ryosuke Uchitate
 
Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)
Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)
Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)オラクルエンジニア通信
 
NTTデータ流 Hadoop活用のすすめ ~インフラ構築・運用の勘所~
NTTデータ流 Hadoop活用のすすめ ~インフラ構築・運用の勘所~NTTデータ流 Hadoop活用のすすめ ~インフラ構築・運用の勘所~
NTTデータ流 Hadoop活用のすすめ ~インフラ構築・運用の勘所~NTT DATA OSS Professional Services
 
Elasticsaerch Runtime Field
Elasticsaerch Runtime FieldElasticsaerch Runtime Field
Elasticsaerch Runtime FieldNomura Yuta
 
Hadoop/Spark で Amazon S3 を徹底的に使いこなすワザ (Hadoop / Spark Conference Japan 2019)
Hadoop/Spark で Amazon S3 を徹底的に使いこなすワザ (Hadoop / Spark Conference Japan 2019)Hadoop/Spark で Amazon S3 を徹底的に使いこなすワザ (Hadoop / Spark Conference Japan 2019)
Hadoop/Spark で Amazon S3 を徹底的に使いこなすワザ (Hadoop / Spark Conference Japan 2019)Noritaka Sekiyama
 
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)NTT DATA Technology & Innovation
 
MHA for MySQLとDeNAのオープンソースの話
MHA for MySQLとDeNAのオープンソースの話MHA for MySQLとDeNAのオープンソースの話
MHA for MySQLとDeNAのオープンソースの話Yoshinori Matsunobu
 
C34 Always On 可用性グループ 構築時のポイント by 小澤真之
C34 Always On 可用性グループ 構築時のポイント by 小澤真之C34 Always On 可用性グループ 構築時のポイント by 小澤真之
C34 Always On 可用性グループ 構築時のポイント by 小澤真之Insight Technology, Inc.
 

What's hot (20)

Fig 9-02
Fig 9-02Fig 9-02
Fig 9-02
 
ストリーム処理におけるApache Avroの活用について(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)
ストリーム処理におけるApache Avroの活用について(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)ストリーム処理におけるApache Avroの活用について(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)
ストリーム処理におけるApache Avroの活用について(NTTデータ テクノロジーカンファレンス 2019 講演資料、2019/09/05)
 
事例から見る規模別クラウド・データベースの選び方 (Oracle Database) (Oracle Cloudウェビナーシリーズ: 2021年6月30日)
事例から見る規模別クラウド・データベースの選び方 (Oracle Database) (Oracle Cloudウェビナーシリーズ: 2021年6月30日)事例から見る規模別クラウド・データベースの選び方 (Oracle Database) (Oracle Cloudウェビナーシリーズ: 2021年6月30日)
事例から見る規模別クラウド・データベースの選び方 (Oracle Database) (Oracle Cloudウェビナーシリーズ: 2021年6月30日)
 
Understanding PostgreSQL LW Locks
Understanding PostgreSQL LW LocksUnderstanding PostgreSQL LW Locks
Understanding PostgreSQL LW Locks
 
InfiniFlux vs influxdb 비교 테스트 결과 2016 12월-v2
InfiniFlux vs influxdb 비교 테스트 결과 2016 12월-v2InfiniFlux vs influxdb 비교 테스트 결과 2016 12월-v2
InfiniFlux vs influxdb 비교 테스트 결과 2016 12월-v2
 
Oracle Cloud PaaS & IaaS:2019年11月度サービス情報アップデート
Oracle Cloud PaaS & IaaS:2019年11月度サービス情報アップデートOracle Cloud PaaS & IaaS:2019年11月度サービス情報アップデート
Oracle Cloud PaaS & IaaS:2019年11月度サービス情報アップデート
 
OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)
OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)
OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)
 
第一次Elasticsearch就上手
第一次Elasticsearch就上手第一次Elasticsearch就上手
第一次Elasticsearch就上手
 
第18回しゃちほこオラクル俱楽部
第18回しゃちほこオラクル俱楽部第18回しゃちほこオラクル俱楽部
第18回しゃちほこオラクル俱楽部
 
ASP.NET MVC Performance
ASP.NET MVC PerformanceASP.NET MVC Performance
ASP.NET MVC Performance
 
Caching ガイダンスの話
Caching ガイダンスの話Caching ガイダンスの話
Caching ガイダンスの話
 
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
 
Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)
Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)
Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)
 
NTTデータ流 Hadoop活用のすすめ ~インフラ構築・運用の勘所~
NTTデータ流 Hadoop活用のすすめ ~インフラ構築・運用の勘所~NTTデータ流 Hadoop活用のすすめ ~インフラ構築・運用の勘所~
NTTデータ流 Hadoop活用のすすめ ~インフラ構築・運用の勘所~
 
OCIコンテナサービス関連の技術詳細
OCIコンテナサービス関連の技術詳細OCIコンテナサービス関連の技術詳細
OCIコンテナサービス関連の技術詳細
 
Elasticsaerch Runtime Field
Elasticsaerch Runtime FieldElasticsaerch Runtime Field
Elasticsaerch Runtime Field
 
Hadoop/Spark で Amazon S3 を徹底的に使いこなすワザ (Hadoop / Spark Conference Japan 2019)
Hadoop/Spark で Amazon S3 を徹底的に使いこなすワザ (Hadoop / Spark Conference Japan 2019)Hadoop/Spark で Amazon S3 を徹底的に使いこなすワザ (Hadoop / Spark Conference Japan 2019)
Hadoop/Spark で Amazon S3 を徹底的に使いこなすワザ (Hadoop / Spark Conference Japan 2019)
 
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
BigtopでHadoopをビルドする(Open Source Conference 2021 Online/Spring 発表資料)
 
MHA for MySQLとDeNAのオープンソースの話
MHA for MySQLとDeNAのオープンソースの話MHA for MySQLとDeNAのオープンソースの話
MHA for MySQLとDeNAのオープンソースの話
 
C34 Always On 可用性グループ 構築時のポイント by 小澤真之
C34 Always On 可用性グループ 構築時のポイント by 小澤真之C34 Always On 可用性グループ 構築時のポイント by 小澤真之
C34 Always On 可用性グループ 構築時のポイント by 小澤真之
 

Similar to Implementation of EAV pattern for ActiveRecord models

Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails Mohit Jain
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelpauldix
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelpauldix
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1Jano Suchal
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererRuby Meditation
 
Ajax nested form and ajax upload in rails
Ajax nested form and ajax upload in railsAjax nested form and ajax upload in rails
Ajax nested form and ajax upload in railsTse-Ching Ho
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KThomas Fuchs
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le WagonAlex Benoit
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaiMasters
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2pyjonromero
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosEdgar Suarez
 
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares DornellesA linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares DornellesTchelinux
 
Ruby Programming Language
Ruby Programming LanguageRuby Programming Language
Ruby Programming LanguageDuda Dornelles
 
Type safe embedded domain-specific languages
Type safe embedded domain-specific languagesType safe embedded domain-specific languages
Type safe embedded domain-specific languagesArthur Xavier
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weiboshaokun
 

Similar to Implementation of EAV pattern for ActiveRecord models (20)

Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
 
Prototype Framework
Prototype FrameworkPrototype Framework
Prototype Framework
 
Ajax nested form and ajax upload in rails
Ajax nested form and ajax upload in railsAjax nested form and ajax upload in rails
Ajax nested form and ajax upload in rails
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le Wagon
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio Akita
 
jQuery
jQueryjQuery
jQuery
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2py
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
 
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares DornellesA linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
 
Ruby Programming Language
Ruby Programming LanguageRuby Programming Language
Ruby Programming Language
 
Type safe embedded domain-specific languages
Type safe embedded domain-specific languagesType safe embedded domain-specific languages
Type safe embedded domain-specific languages
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
 

Recently uploaded

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 

Recently uploaded (20)

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 

Implementation of EAV pattern for ActiveRecord models

  • 1. Implementation of EAV pattern for ActiveRecord models Kostyantyn Stepanyuk kostya.stepanyuk@gmail.com https://github.com/kostyantyn
  • 7. Specification 1. Save Entity Type as string in Entity Table (STI pattern) 2. Keep attributes directly in the model 3. Use Polymorphic Association between Entity and Value
  • 8. Migration class CreateEntityAndValues < ActiveRecord::Migration def change create_table :products do |t| t.string :type t.string :name t.timestamps end %w(string integer float boolean).each do |type| create_table "#{type}_attributes" do |t| t.references :entity, polymorphic: true t.string :name t.send type, :value t.timestamps end end end end
  • 9. Attribute Models class Attribute < ActiveRecord::Base self.abstract_class = true attr_accessible :name, :value belongs_to :entity, polymorphic: true, touch: true, autosave: true end class BooleanAttribute < Attribute end class FloatAttribute < Attribute end class IntegerAttribute < Attribute end class StringAttribute < Attribute end
  • 10. Product class Product < ActiveRecord::Base %w(string integer float boolean).each do |type| has_many :"#{type}_attributes", as: :entity, autosave: true, dependent: :delete_all end def eav_attr_model(name, type) attributes = send("#{type}_attributes") attributes.detect { |attr| attr.name == name } || attributes.build(name: name) end class << self def eav(name, type) class_eval <<-EOS, __FILE__, __LINE__ + 1 attr_accessible :#{name} def #{name}; eav_attr_model('#{name}', '#{type}').value end def #{name}=(value) eav_attr_model('#{name}', '#{type}').value = value end def #{name}?; eav_attr_model('#{name}', '#{type}').value? end EOS end end end
  • 11. Simple Product class SimpleProduct < Product attr_accessible :name eav :code, :string eav :price, :float eav :quantity, :integer eav :active, :boolean end
  • 12. Advanced Attribute Methods class Product < ActiveRecord::Base def self.eav(name, type) attr_accessor name attribute_method_matchers.each do |matcher| class_eval <<-EOS, __FILE__, __LINE__ + 1 def #{matcher.method_name(name)}(*args) eav_attr_model('#{name}', '#{type}').send :#{matcher.method_name('value')}, *args end EOS end end end
  • 13. Usage SimpleProduct.create(code: '#1', price: 2.75, quantity: 5, active: true).id # 1 product = SimpleProduct.find(1) product.code # "#1" product.price # 2.75 product.quantity # 5 product.active? # true product.code_changed? # false product.code = 3.50 product.code_changed? # true product.code_was # 2.75 SimpleProduct.instance_methods.first(10) # [:code, :code=, :code_before_type_cast, :code?, :code_changed?, : code_change, :code_will_change!, :code_was, :reset_code!, :_code]
  • 14. What about query methods? class Product < ActiveRecord::Base def self.scoped(options = nil) super(options).extend(QueryMethods) end module QueryMethods def select(*args, &block) super(*args, &block) end def order(*args) super(*args) end def where(*args) super(*args) end end end
  • 16. Installation class Product < ActiveRecord::Base attr_accessor :title, :code, :quantity, :price, :active, :description define_hydra_attributes do string :title, :code integer :quantity float :price boolean :active text :description end end class GenerateAttributes < ActiveRecord::Migration def up HydraAttribute::Migration.new(self).migrate end def down HydraAttribute::Migration.new(self).rollback end end
  • 17. Helper Methods Product.hydra_attributes # [{'code' => :string, 'price' => :float, 'quantity' => :integer, 'active' => :boolean}] Product.hydra_attribute_names # ['code', 'price', 'quantity', 'active'] Product.hydra_attribute_types # [:string, :float, :integer, :boolean] Product.new.attributes # [{'name' => nil, 'code' => nil, 'price' => nil, 'quantity' => nil, 'active' => nil}] Product.new.hydra_attributes # [{'code' => nil, 'price' => nil, 'quantity' => nil, 'active' => nil}]
  • 18. Where Condition Product.create(price: 2.50) # id: 1 Product.create(price: nil) # id: 2 Product.create # id: 3 Product.where(price: 2.50).map(&:id) # [1] Product.where(price: nil).map(&:id) # [2, 3]
  • 19. Select Attributes Product.create(price: 2.50) # id: 1 Product.create(price: nil) # id: 2 Product.create # id: 3 Product.select(:price).map(&:attributes) # [{'price' => 2.50}, {'price => nil}, {'price' => nil}] Product.select(:price).map(&:code) # ActiveModel::MissingAttributeError: missing attribute: code
  • 20. Order and Reverse Order Product.create(title: 'a') # id: 1 Product.create(title: 'b') # id: 2 Product.create(title: 'c') # id: 3 Product.order(:title).first.id # 1 Product.order(:title).reverse_order.first.id # 3