Skip to content

Instantly share code, notes, and snippets.

@pangui
Created September 22, 2023 01:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pangui/28b45c3601395ef52df649a7ef84388b to your computer and use it in GitHub Desktop.
Save pangui/28b45c3601395ef52df649a7ef84388b to your computer and use it in GitHub Desktop.
require 'json'
class Person
@age = nil
attr_accessor :json_field, :age
def initialize *args
# useful for Rails ApplicationRecord models
args[0].each{|key, value| self.send("#{key}=".to_sym, value)}
# uncomment next line for inherited classes
# super *args
end
# catch missing methods
def method_missing name, *args
# @davidbella's inspiration: https://gist.github.com/davidbella/6918455
# define json accessor to read/write data in json_field
attribute_name = name.to_s.gsub(/=$/, '')
self.json_field ||= {}
# define charles.{attribute_name} = value
self.class.send(:define_method, "#{attribute_name}=".to_sym) do |value|
self.json_field.send(:[]=, attribute_name, value)
end
# define charles.{attribute_name}
self.class.send(:define_method, attribute_name.to_sym) do
value = self.json_field.send(:[], attribute_name)
end
# call defined method
send(name, *args)
end
# Just for object inspection
def to_h
Hash[instance_variables.map{|var| [var, instance_variable_get(var)] }]
end
end
# Initialize instance and assign dynamic and static attributes
charles = Person.new({first_name: 'Charles', age: 35})
#
# Verify dynamic attribute
puts charles.first_name.inspect
# -> "Charles"
#
# Assign more dynamic variables and check json field
charles.country, charles.city = 'UK', 'London'
puts JSON.pretty_generate(charles.json_field)
# -> {
# "first_name": "Charles",
# "country": "UK",
# "city": "London"
# }
#
# Inspect instance attributes
puts JSON.pretty_generate(charles.to_h)
# -> {
# "@json_field": {
# "first_name": "Charles",
# "country": "UK",
# "city": "London"
# },
# "@age": 35
# }
#
# For ApplicationRecord, remember to notfify changes before save
# charles.json_field_will_change!
# charles.save
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment