Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

candywrapper

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

candywrapper

  • 0.0.1
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

Candywrapper

This gem provides simple wrapper around a regular ruby Hash object. This wrapper provides the following functionality:

  • DSL for defining arbitrarily deep serializable structure
  • JSON serialization

This gem is useful when you want to serialize/deserialize Ruby objects to store or to transmit them over network. This gem was designed with the following advantages in mind:

  1. You can mix-in the functionality to existing Ruby objects.

  2. DSL explicitly defines the protocol payload

    • Serialization only includes whatever is defined via DSL. All other object states are ignored. This clearly delineates object states that are transient from those that are to be preserved across serialization.
    • Attributes defined via Candywrapper DSL are called "serializable attributes".
  3. Light-weight and fast

    • Serialization payload is represented by a single hash object (containing nested hashes). There is no other bookkeeping going on other than that.
    • (De-)Serialization is fast since we just use C-compiled JSON gem of the 1 hash object. We never recursively traverse the nested hash structure, since doing that in Ruby would be 50-70 times slower than in C.
  4. You can nest candywrappers inside candywrappers.

    • If you nest candywrapper object 2 and object 3 inside candywrapper object 1, there is still only 1 nested hash object wrapped by object 1. In this case, the hash object used by objects 2 and 3 are nested inside the hash object used by object 1. This means that we only ever pass 1 hash object to json generator during serialization.
    • What happens to object 2 and object 3 in the above story? Those objects are just wrappers around the nested (sub-) hashes of object 1's hash. All these relationships / references are correctly maintained within the accessor methods.

Given this design, please be aware that:

  1. Any object state that you want to save or send should be stored in the wrapped hash object. (see usage)

  2. The only types that can be stored as serializable attribute are basic JSON primitives, or other candywrapper objects. (see usage) For example, you cannot store a File object in a candywrapper attribute.

  3. We do not support multiple references to the same object, circular or not. If you assign the same complex object across multiple serializable attributes, the behavior is undefined. (depending on how JSON generator implementation behaves)

  4. Cloning a candywrapper object (.clone) will perform deep copy. If we don't do this, you could end up with two separate objects sharing the same internal state.

  5. All serializable attributes are optional in nature. If you don't set them, they won't be part of the serialized payload.

Known Issues / Todo

  1. We do not provide validation of values being assigned to serializable attributes. The reason for this is to keep things as minimal as possible. If we were to provide validation, we would also have to go through any nested raw hash object to see if they satisfy the structure specified in DSL, which means recursively traversing all the elements of the raw hash during deserialization.

    The only thing that we check for you is whether something is allowed to be nil or not, as such feature tends to catch a lot of real bugs.

  2. Currently, we do not support nested array of candywrappers. For now, arrays must only contain other JSON primitives. When we support this in the future, we will probably require each array explicitly define the element type, and we will not allow mixing of multiple candywrapper types within the same array.

  3. Currently, we do not support arbitrary hash containing candywrappers as values. The reason for this is that to support deserializing a candywrapper object from value within an arbitrarily nested hash object requires decorating the raw payload. (e.g. mark a hash object as being payload of a candywrapper class using '_class_name' key)

Related advice here is that you stick to explicitly defining your object structure, rather than leaving it up to some run-time interpretation (based on existence of a specific key-val). I've tried to support this kind of functionality before in a previous job, and it became pretty ugly.

Installation

Add this line to your application's Gemfile:

gem 'candywrapper'

And then execute:

$ bundle

Or install it yourself as:

$ gem install candywrapper

Usage

Here is a simple example to illustrate how to use Candywrapper.

require 'candywrapper'

class Address
  include Candywrapper
  serializable_attr :street
  serializable_attr :city
  serializable_attr :state
  serializable_attr :zip
end

class Person
  include Candywrapper
  serializable_attr :first_name
  serializable_attr :middle_name
  serializable_attr :last_name
  serializable_attr :home_address, Address
  serializable_attr :work_address, Address
  def full_name
    @full_name = [first_name, middle_name, last_name].compact.join(" ")
  end
end

a = Address.new
a.street = "120 Cherry ST N"
a.city = "Seattle"
a.state = "WA"
a.zip = "98101"

p = Person.new
p.home_address = a
p.first_name = "James"
p.last_name = "Bond"
p.full_name           # => "James Bond"

json = p.serialize_to_json
# => 
# {
#     "first_name": "James", 
#     "last_name": "Bond", 
#     "home_address": {
#         "street": "120 Cherry ST N", 
#         "city": "Seattle", 
#         "state": "WA", 
#         "zip": "98101"
#     }
# }

p2 = Person.deserialize_from_json(json)
p2.class              # => Person
p2.home_address.class # => Address
p2.work_address       # => nil
p2.full_name          # => "James Bond"

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

FAQs

Package last updated on 20 Aug 2012

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc