Skip to content

Instantly share code, notes, and snippets.

@skojin
Created February 13, 2017 08:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skojin/097a1077bfc607cfabbf039f6140060a to your computer and use it in GitHub Desktop.
Save skojin/097a1077bfc607cfabbf039f6140060a to your computer and use it in GitHub Desktop.
# Each record of this class store one extra attribute for each model
# Used to store not important data need for reports, data sync, and etc
class ExtraValue < ActiveRecord::Base
belongs_to :record, polymorphic: true
scope :type, ->(klass){ where(record_type: klass) }
scope :record, ->(r){ where(record_id: r.id, record_type: r.class) }
class << self
# usage: set(record, 'extra_attr', "text")
# @param type - column type
def set(record, name, value, type: :s)
connection.execute(
"INSERT INTO #{table_name} (record_id, record_type, `name`, value_#{type}) VALUES (#{connection.quote record.id}, #{connection.quote record.class.to_s}, #{connection.quote name}, #{connection.quote value}) ON DUPLICATE KEY UPDATE value_#{type} = #{connection.quote value}"
)
end
def get(record, name)
ExtraValue.record(record).where(name: name).pluck(:value_s).first
end
end
# use in AR models
# extra_value_attr :extra_name
module Attribute
def extra_value_attr(attr_name, type: :s)
mixin = Module.new do
define_method(attr_name) do
ExtraValue.get(self, attr_name)
end
define_method("#{attr_name}=") do |v|
ExtraValue.set(self, attr_name, v, type: type)
end
end
prepend mixin
end
end
end
# == Schema Information
#
# Table name: extra_values
#
# id :integer not null, primary key
# record_id :integer not null, indexed => [record_type, name]
# record_type :string(255) not null, indexed => [record_id, name]
# name :string(255) not null, indexed => [record_id, record_type]
# value_s :string(255)
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment