LazyDoc
An implementation of the Embedded Document pattern for POROs.
LazyDoc provides a declarative DSL for extracting deeply nested values from a JSON document. The embedded JSON is lazily parsed so that needed attributes from the document are only parsed when accessed. Finally, parsed values are cached so that subsequent access does not access the JSON again.
Currently, LazyDoc only supports JSON. XML support may be added later.
Installation
Add this line to your application's Gemfile:
gem 'lazy_doc'
DSL Options
- Basic usage.
access
:access :name
will look for a property called 'name' at the top level of the embedded document. -
access :name, :phone, :address
will look for all three properties. This option does not currently support using any options. -
via
:access :job, via: [:profile, :occupation]
will look for a property called 'job' by parsing through 'profile' -> 'occupation'. -
default
:access :currency, default: 'USD'
will use the default value of 'USD' if the currency attribute is set to an empty value (empty?
ornil?
) -
finally
:access :initials, finally: lambda { |initials| initials.upcase }
will call the supplied block, passing in 'initials,' and will return the result of that block. -
as
:access :profile, as: Profile
will pass the sub-document found at 'profile' into a new 'Profile' object, and will return the newly constructed Profile object. This is great for constructing nested LazyDoc relationships. -
extract
:access :customers, extract: :name
will make the assumption that the attribute 'customers' will be an array of objects and will extract the 'name' property from each object and return an array of 'names' (This would be the equivalent of the Enumerable#map method)
Example Usage
class User
include LazyDoc::DSL
access :name # Access the attribute "name"
access :address, via: :streetAddress # Access the attribute "streetAddress"
access :job, via: [:profile, :occupation, :title] # Access the attribute "title" found at "profile" -> "occupation"
def initialize(json)
lazily_embed(json) # Initialize the LazyDoc object
end
end
json = '{"name": "George Washington", "streetAddress": "The White House", "profile": {"occupation": {"title": "President"}}}'
user = User.new(json)
puts user.name
puts user.address
puts user.job
Collections
When the document has a top-level array, use the LazyDoc::Collection
class to transform it into an array of LazyDoc objects.
usage:
class User
include LazyDoc::DSL
access :name
# more...
end
json = '[{"name": "Brian"}, {"name": "Chris"}]'
users = LazyDoc::Collection.build(json, User)
users.each do |user|
puts user.name
end
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request