Last active
August 29, 2015 14:13
-
-
Save pmn4/9fb598e4f4a8313c0155 to your computer and use it in GitHub Desktop.
Ruby Classes as Hash Wrappers (for faster serialization)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# More often than not at @RTR_tech, our ruby layer is a pass-through from our | |
# services to our client application. In those cases, it doesn't make much | |
# sense to parse the JSON string. | |
# | |
# Other times, however, we want to work with the objects that come back, so | |
# like good ruby developers, we create classes which reflect the data we | |
# expect, but as an intermittant step, we convert the JSON to a Hash, which | |
# we convert to an object. | |
# | |
# The latter case can get expensive, _especially_ when we don't even use the | |
# object that we create. | |
# | |
# With these two considerations in mind, consider the following code which | |
# lazily parses a JSON string iff some other ruby code needs it. Additionally, | |
# it only calls #to_json if data has changed, otherwise it simply returns the | |
# original JSON string. | |
# | |
# let me know what you think! | |
require 'json' | |
class ServiceResponseObject | |
# Internals: | |
# attr_accessor :json, :hash | |
def initialize(json) | |
# Store the json string, to be returned via #to_json if nothing changes | |
@__json = json | |
end | |
def as_json(*args) | |
# ActiveModel? great! as_json ftw | |
__hash.as_json(*args) if __hash.respond_to?(:as_json) | |
__hash | |
end | |
def to_json(*args) | |
# Unless the internally stored json string has been wiped out, return it | |
return @__json unless @__json.nil? | |
# re-jsonify self | |
@__json = as_json(*args).to_json | |
end | |
class << self | |
# Defines getters and setters on your class | |
# @param [symbol] accessor - accessor methods name | |
# @param [string] key - hash key where data is stored for this accessor | |
def field(accessor, key) | |
# `field :abc, 'xyz'` yields the inline comments below | |
class_eval %Q{ | |
def #{accessor} # def abc | |
__hash['#{key}'] # __hash['xyz'] | |
end # end | |
def #{accessor}=(val) # def abc=(val) | |
@__json = nil unless __hash['#{key}'] == val # @__json = nil unless __hash['xyz'] == val | |
__hash['#{key}'] = val # __hash['xyz'] = val | |
end # end | |
} | |
end | |
end | |
private | |
# Lazy-load the internal Hash | |
def __hash | |
@__hash ||= JSON.parse(@__json) | |
end | |
end |
Author
pmn4
commented
Jan 13, 2015
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment