Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BSON support provided through bson gem. #163

Merged
merged 1 commit into from
Feb 12, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RABL #

RABL (Ruby API Builder Language) is a Rails and [Padrino](http://padrinorb.com) ruby templating system for generating JSON and XML. When using the ActiveRecord 'to_json' method, I tend to quickly find myself wanting a more expressive and powerful solution for generating APIs.
RABL (Ruby API Builder Language) is a Rails and [Padrino](http://padrinorb.com) ruby templating system for generating JSON, XML, MessagePack and BSON. When using the ActiveRecord 'to_json' method, I tend to quickly find myself wanting a more expressive and powerful solution for generating APIs.
This is especially frustrating when the JSON representation is complex or doesn't match the exact schema defined in the database.

I wanted a simple and flexible system for generating my APIs. In particular, I wanted to easily:
Expand Down Expand Up @@ -100,8 +100,10 @@ Rabl.configure do |config|
# Commented as these are the defaults
# config.json_engine = nil # Any multi\_json engines
# config.msgpack_engine = nil # Defaults to ::MessagePack
# config.bson_engine = nil # Defaults to ::BSON
# config.include_json_root = true
# config.include_msgpack_root = true
# config.include_bson_root = true
# config.include_xml_root = false
# config.enable_json_callbacks = false
# config.xml_options = { :dasherize => true, :skip_types => false }
Expand Down Expand Up @@ -145,6 +147,37 @@ end

*NOTE*: Attempting to render the msgpack format without either including the msgpack gem or setting a `msgpack_engine` will cause an exception to be raised.

### BSON ###

Rabl also includes optional support for [BSON](http://bsonspec.org/) serialization format using the [bson gem](https://rubygems.org/gems/bson).
To enable, include the bson gem in your project's Gemfile. Then use Rabl as normal with the `bson` format (akin to json and xml formats).

```ruby
# Gemfile
gem 'bson', '~> 1.5.2'
```
To use it with Rails just register bson mime type format.
```ruby
# config/initializers/mime_types.rb
Mime::Type.register "application/bson", :bson
```

One can additionally use a custom BSON implementation by setting the Rabl `bson_engine` configuration attribute. This custom BSON engine must conform to the BSON#serialize method signature.

```ruby
class CustomEncodeEngine
def self.serialize string
# Custom Encoding by your own engine.
end
end

Rabl.configure do |config|
config.bson_engine = CustomEncodeEngine
end
```

*NOTE*: Attempting to render the bson format without either including the bson gem or setting a `bson_engine` will cause an exception to be raised.

## Usage ##

### Object Assignment ###
Expand Down
20 changes: 20 additions & 0 deletions lib/rabl/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
rescue LoadError
end

# We load the bson library if it is available.
begin
require 'bson'
rescue LoadError
end

# Load MultiJSON
require 'multi_json'

Expand All @@ -13,8 +19,12 @@ class Configuration
attr_accessor :include_json_root
attr_accessor :include_msgpack_root
attr_accessor :include_xml_root
attr_accessor :include_bson_root
attr_accessor :enable_json_callbacks
attr_accessor :bson_check_keys
attr_accessor :bson_move_id
attr_writer :msgpack_engine
attr_writer :bson_engine
attr_writer :xml_options

DEFAULT_XML_OPTIONS = { :dasherize => true, :skip_types => false }
Expand All @@ -23,9 +33,13 @@ def initialize
@include_json_root = true
@include_msgpack_root = true
@include_xml_root = false
@include_bson_root = true
@enable_json_callbacks = false
@bson_check_keys = false
@bson_move_id = false
@json_engine = nil
@msgpack_engine = nil
@bson_engine = nil
@xml_options = {}
end

Expand All @@ -47,6 +61,12 @@ def msgpack_engine
@msgpack_engine || ::MessagePack
end

##
# @return the Bson encoder/engine to use.
def bson_engine
@bson_engine || ::BSON
end

# Allows config options to be read like a hash
#
# @param [Symbol] option Key for a given attribute
Expand Down
16 changes: 16 additions & 0 deletions lib/rabl/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ def to_xml(options={})
to_hash(options).to_xml(xml_options)
end

# Returns a bson representation of the data object
# to_bson(:root => true)
def to_bson(options={})
include_root = Rabl.configuration.include_bson_root
options = options.reverse_merge(:root => include_root, :child_root => include_root)
result = if defined?(@_collection_name)
{ @_collection_name => to_hash(options) }
elsif defined?(@_bson_collection_name)
{ @_bson_collection_name => to_hash(options) }
else
to_hash(options)
end
Rabl.configuration.bson_engine.serialize(result).to_s
end

# Sets the object to be used as the data source for this template
# object(@user)
# object @user => :person
Expand All @@ -85,6 +100,7 @@ def object(data)
# collection @users => :people
def collection(data)
@_collection_name = data.values.first if data.respond_to?(:each_pair)
@_bson_collection_name = data_name(data) if is_collection?(data)
self.object(data_object(data).to_a) if data
end

Expand Down
4 changes: 3 additions & 1 deletion lib/rabl/helpers.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'active_support/inflector' # for the sake of pluralizing

module Rabl
module Helpers
# data_object(data) => <AR Object>
Expand All @@ -18,7 +20,7 @@ def data_name(data)
return data.values.first if data.is_a?(Hash) # @user => :user
data = @_object.send(data) if data.is_a?(Symbol) && @_object # :address
if data.respond_to?(:first)
data_name(data.first).pluralize if data.first.present?
data_name(data.first).to_s.pluralize if data.first.present?
else # actual data object
object_name = @_collection_name.to_s.singularize if defined? @_collection_name
object_name ||= data.class.respond_to?(:model_name) ? data.class.model_name.element : data.class.to_s.downcase
Expand Down
5 changes: 3 additions & 2 deletions rabl.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ Gem::Specification.new do |s|
s.authors = ["Nathan Esquenazi"]
s.email = ["nesquena@gmail.com"]
s.homepage = "https://github.com/nesquena/rabl"
s.summary = %q{General ruby templating for json or xml}
s.description = %q{General ruby templating for json or xml}
s.summary = %q{General ruby templating with json, bson, xml and msgpack support}
s.description = %q{General ruby templating with json, bson, xml and msgpack support}

s.rubyforge_project = "rabl"

Expand All @@ -28,4 +28,5 @@ Gem::Specification.new do |s|
s.add_development_dependency 'tilt'
s.add_development_dependency 'yajl-ruby'
s.add_development_dependency 'msgpack', '~> 0.4.5'
s.add_development_dependency 'bson', '~> 1.5.2'
end
Loading