Skip to content
This repository

BSON support provided through bson gem. #163

Merged
merged 1 commit into from about 2 years ago

4 participants

Andrey Voronkov Andrey Ognevsky Oleg Balbekov Nathan Esquenazi
Andrey Voronkov

Features:

  • no tests :trollface:
  • collection should always be wrapped into hash (implemented into to_bson) because of BSON.serialize accepts only hash.
Andrey Ognevsky

I've tried add bson support to Rabl couple months ago, but something gone wrong.
Great work, thanks!

Nathan Esquenazi
Owner

Sweet, great to have BSON support. If we can add something akin to https://github.com/nesquena/rabl/blob/master/test/msgpack_engine_test.rb for BSON, I will merge this and release a new gem version.

Andrey Voronkov

I think I'll provide some tests soon - lack of time for today.

Nathan Esquenazi
Owner

Awesome thanks for working on this.

Andrey Voronkov BSON format support provided. Fixed pluralization (without requiring …
…active_support/inflector it doesn't work in Rabl::Helpers). Covered by tests, results were compared with msgpack results and matches except for those that returns array - BSON.serialize can't accept arrays so it wraps it into a hash with first object name pluralization as a key.
b9ec72b
Andrey Voronkov

I've just corrected my previous commit. Not it is covered by tests, bugs are fixed and it works as needed.

Nathan Esquenazi nesquena merged commit f4aed40 into from February 12, 2012
Nathan Esquenazi nesquena closed this February 12, 2012
Nathan Esquenazi
Owner

OK, added you to the readme, updated the changelog and pushed out 0.5.5.e. Let me know if everything looks OK.

Ismael Abreu ismaelga referenced this pull request from a commit February 15, 2013
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Feb 12, 2012
Andrey Voronkov BSON format support provided. Fixed pluralization (without requiring …
…active_support/inflector it doesn't work in Rabl::Helpers). Covered by tests, results were compared with msgpack results and matches except for those that returns array - BSON.serialize can't accept arrays so it wraps it into a hash with first object name pluralization as a key.
b9ec72b
This page is out of date. Refresh to see the latest.
35  README.md
Source Rendered
... ...
@@ -1,6 +1,6 @@
1 1
 # RABL #
2 2
 
3  
-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.
  3
+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.
4 4
 This is especially frustrating when the JSON representation is complex or doesn't match the exact schema defined in the database.
5 5
 
6 6
 I wanted a simple and flexible system for generating my APIs. In particular, I wanted to easily:
@@ -100,8 +100,10 @@ Rabl.configure do |config|
100 100
   # Commented as these are the defaults
101 101
   # config.json_engine = nil # Any multi\_json engines
102 102
   # config.msgpack_engine = nil # Defaults to ::MessagePack
  103
+  # config.bson_engine = nil # Defaults to ::BSON
103 104
   # config.include_json_root = true
104 105
   # config.include_msgpack_root = true
  106
+  # config.include_bson_root = true
105 107
   # config.include_xml_root  = false
106 108
   # config.enable_json_callbacks = false
107 109
   # config.xml_options = { :dasherize  => true, :skip_types => false }
@@ -145,6 +147,37 @@ end
145 147
 
146 148
 *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.
147 149
 
  150
+### BSON ###
  151
+
  152
+Rabl also includes optional support for [BSON](http://bsonspec.org/) serialization format using the [bson gem](https://rubygems.org/gems/bson).
  153
+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).
  154
+
  155
+```ruby
  156
+# Gemfile
  157
+gem 'bson', '~> 1.5.2'
  158
+```
  159
+To use it with Rails just register bson mime type format.
  160
+```ruby
  161
+# config/initializers/mime_types.rb
  162
+Mime::Type.register "application/bson", :bson
  163
+```
  164
+
  165
+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.
  166
+
  167
+```ruby
  168
+class CustomEncodeEngine
  169
+  def self.serialize string
  170
+    # Custom Encoding by your own engine.
  171
+  end
  172
+end
  173
+
  174
+Rabl.configure do |config|
  175
+  config.bson_engine = CustomEncodeEngine
  176
+end
  177
+```
  178
+
  179
+*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.
  180
+
148 181
 ## Usage ##
149 182
 
150 183
 ### Object Assignment ###
20  lib/rabl/configuration.rb
@@ -4,6 +4,12 @@
4 4
 rescue LoadError
5 5
 end
6 6
 
  7
+# We load the bson library if it is available.
  8
+begin
  9
+  require 'bson'
  10
+  rescue LoadError
  11
+end
  12
+
7 13
 # Load MultiJSON
8 14
 require 'multi_json'
9 15
 
@@ -13,8 +19,12 @@ class Configuration
13 19
     attr_accessor :include_json_root
14 20
     attr_accessor :include_msgpack_root
15 21
     attr_accessor :include_xml_root
  22
+    attr_accessor :include_bson_root
16 23
     attr_accessor :enable_json_callbacks
  24
+    attr_accessor :bson_check_keys
  25
+    attr_accessor :bson_move_id
17 26
     attr_writer   :msgpack_engine
  27
+    attr_writer   :bson_engine
18 28
     attr_writer   :xml_options
19 29
 
20 30
     DEFAULT_XML_OPTIONS = { :dasherize  => true, :skip_types => false }
@@ -23,9 +33,13 @@ def initialize
23 33
       @include_json_root     = true
24 34
       @include_msgpack_root  = true
25 35
       @include_xml_root      = false
  36
+      @include_bson_root     = true
26 37
       @enable_json_callbacks = false
  38
+      @bson_check_keys       = false
  39
+      @bson_move_id          = false
27 40
       @json_engine           = nil
28 41
       @msgpack_engine        = nil
  42
+      @bson_engine           = nil
29 43
       @xml_options           = {}
30 44
     end
31 45
 
@@ -47,6 +61,12 @@ def msgpack_engine
47 61
       @msgpack_engine || ::MessagePack
48 62
     end
49 63
 
  64
+    ##
  65
+    # @return the Bson encoder/engine to use.
  66
+    def bson_engine
  67
+      @bson_engine || ::BSON
  68
+    end
  69
+
50 70
     # Allows config options to be read like a hash
51 71
     #
52 72
     # @param [Symbol] option Key for a given attribute
16  lib/rabl/engine.rb
@@ -72,6 +72,21 @@ def to_xml(options={})
72 72
       to_hash(options).to_xml(xml_options)
73 73
     end
74 74
 
  75
+    # Returns a bson representation of the data object
  76
+    # to_bson(:root => true)
  77
+    def to_bson(options={})
  78
+      include_root = Rabl.configuration.include_bson_root
  79
+      options = options.reverse_merge(:root => include_root, :child_root => include_root)
  80
+      result = if defined?(@_collection_name)
  81
+                 { @_collection_name => to_hash(options) }
  82
+               elsif defined?(@_bson_collection_name)
  83
+                 { @_bson_collection_name => to_hash(options) }
  84
+               else
  85
+                 to_hash(options)
  86
+               end
  87
+      Rabl.configuration.bson_engine.serialize(result).to_s
  88
+    end
  89
+
75 90
     # Sets the object to be used as the data source for this template
76 91
     # object(@user)
77 92
     # object @user => :person
@@ -85,6 +100,7 @@ def object(data)
85 100
     # collection @users => :people
86 101
     def collection(data)
87 102
       @_collection_name = data.values.first if data.respond_to?(:each_pair)
  103
+      @_bson_collection_name = data_name(data) if is_collection?(data)
88 104
       self.object(data_object(data).to_a) if data
89 105
     end
90 106
 
4  lib/rabl/helpers.rb
... ...
@@ -1,3 +1,5 @@
  1
+require 'active_support/inflector' # for the sake of pluralizing
  2
+
1 3
 module Rabl
2 4
   module Helpers
3 5
     # data_object(data) => <AR Object>
@@ -18,7 +20,7 @@ def data_name(data)
18 20
       return data.values.first if data.is_a?(Hash) # @user => :user
19 21
       data = @_object.send(data) if data.is_a?(Symbol) && @_object # :address
20 22
       if data.respond_to?(:first)
21  
-        data_name(data.first).pluralize if data.first.present?
  23
+        data_name(data.first).to_s.pluralize if data.first.present?
22 24
       else # actual data object
23 25
         object_name = @_collection_name.to_s.singularize if defined? @_collection_name
24 26
         object_name ||= data.class.respond_to?(:model_name) ? data.class.model_name.element : data.class.to_s.downcase
5  rabl.gemspec
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
9 9
   s.authors     = ["Nathan Esquenazi"]
10 10
   s.email       = ["nesquena@gmail.com"]
11 11
   s.homepage    = "https://github.com/nesquena/rabl"
12  
-  s.summary     = %q{General ruby templating for json or xml}
13  
-  s.description = %q{General ruby templating for json or xml}
  12
+  s.summary     = %q{General ruby templating with json, bson, xml and msgpack support}
  13
+  s.description = %q{General ruby templating with json, bson, xml and msgpack support}
14 14
 
15 15
   s.rubyforge_project = "rabl"
16 16
 
@@ -28,4 +28,5 @@ Gem::Specification.new do |s|
28 28
   s.add_development_dependency 'tilt'
29 29
   s.add_development_dependency 'yajl-ruby'
30 30
   s.add_development_dependency 'msgpack', '~> 0.4.5'
  31
+  s.add_development_dependency 'bson', '~> 1.5.2'
31 32
 end
331  test/bson_engine_test.rb
... ...
@@ -0,0 +1,331 @@
  1
+require File.expand_path('../teststrap', __FILE__)
  2
+require File.expand_path('../../lib/rabl', __FILE__)
  3
+require File.expand_path('../../lib/rabl/template', __FILE__)
  4
+require File.expand_path('../models/user', __FILE__)
  5
+
  6
+context "Rabl::Engine" do
  7
+
  8
+  helper(:rabl) { |t| RablTemplate.new("code", :format => 'bson') { t } }
  9
+
  10
+  context "with bson defaults" do
  11
+    setup do
  12
+      Rabl.configure do |config|
  13
+        # Comment this line out because include_bson_root is default.
  14
+        #config.include_bson_root = true
  15
+      end
  16
+    end
  17
+
  18
+    context "#object" do
  19
+
  20
+      asserts "that it sets data source" do
  21
+        template = rabl %q{
  22
+          object @user
  23
+        }
  24
+        scope = Object.new
  25
+        scope.instance_variable_set :@user, User.new
  26
+        template.render(scope)
  27
+      end.matches "\x10\x00\x00\x00\x03user\x00\x05\x00\x00\x00\x00\x00"
  28
+
  29
+      asserts "that it can set root node" do
  30
+        template = rabl %q{
  31
+          object @user => :person
  32
+        }
  33
+        scope = Object.new
  34
+        scope.instance_variable_set :@user, User.new
  35
+        template.render(scope).split("").sort
  36
+      end.equals "\x12\x00\x00\x00\x03person\x00\x05\x00\x00\x00\x00\x00".split("").sort
  37
+    end
  38
+
  39
+    context "#collection" do
  40
+
  41
+      asserts "that it sets object to be casted as a simple array" do
  42
+        template = rabl %{
  43
+          collection @users
  44
+        }
  45
+        scope = Object.new
  46
+        scope.instance_variable_set :@users, [User.new, User.new]
  47
+        template.render(scope).split("").sort
  48
+      end.equals "7\x00\x00\x00\x04users\x00+\x00\x00\x00\x030\x00\x10\x00\x00\x00\x03user\x00\x05\x00\x00\x00\x00\x00\x031\x00\x10\x00\x00\x00\x03user\x00\x05\x00\x00\x00\x00\x00\x00\x00".split("").sort
  49
+
  50
+      asserts "that it sets root node for objects" do
  51
+        template = rabl %{
  52
+          collection @users => :people
  53
+        }
  54
+        scope = Object.new
  55
+        scope.instance_variable_set :@users, [User.new, User.new]
  56
+        template.render(scope).split("").sort
  57
+      end.equals "<\x00\x00\x00\x04people\x00/\x00\x00\x00\x030\x00\x12\x00\x00\x00\x03person\x00\x05\x00\x00\x00\x00\x00\x031\x00\x12\x00\x00\x00\x03person\x00\x05\x00\x00\x00\x00\x00\x00\x00".split("").sort
  58
+
  59
+    end
  60
+
  61
+    context "#attribute" do
  62
+
  63
+      asserts "that it adds an attribute or method to be included in output" do
  64
+        template = rabl %{
  65
+          object @user
  66
+          attribute :name
  67
+        }
  68
+        scope = Object.new
  69
+        scope.instance_variable_set :@user, User.new(:name => 'irvine')
  70
+        template.render(scope).split("").sort
  71
+      end.equals "!\x00\x00\x00\x03user\x00\x16\x00\x00\x00\x02name\x00\a\x00\x00\x00irvine\x00\x00\x00".split("").sort
  72
+
  73
+      asserts "that it can add attribute under a different key name through :as" do
  74
+        template = rabl %{
  75
+          object @user
  76
+          attribute :name, :as => 'city'
  77
+        }
  78
+        scope = Object.new
  79
+        scope.instance_variable_set :@user, User.new(:name => 'irvine')
  80
+        template.render(scope).split("").sort
  81
+      end.equals "!\x00\x00\x00\x03user\x00\x16\x00\x00\x00\x02city\x00\a\x00\x00\x00irvine\x00\x00\x00".split("").sort
  82
+
  83
+      asserts "that it can add attribute under a different key name through hash" do
  84
+        template = rabl %{
  85
+          object @user
  86
+          attribute :name => :city
  87
+        }
  88
+        scope = Object.new
  89
+        scope.instance_variable_set :@user, User.new(:name => 'irvine')
  90
+        template.render(scope).split("").sort
  91
+      end.equals "!\x00\x00\x00\x03user\x00\x16\x00\x00\x00\x02city\x00\a\x00\x00\x00irvine\x00\x00\x00".split("").sort
  92
+
  93
+    end
  94
+
  95
+    context "#code" do
  96
+
  97
+      asserts "that it can create an arbitraty code node" do
  98
+        template = rabl %{
  99
+          code(:foo) { 'bar' }
  100
+        }
  101
+        template.render(Object.new).split("").sort
  102
+      end.equals "\x12\x00\x00\x00\x02foo\x00\x04\x00\x00\x00bar\x00\x00".split("").sort
  103
+
  104
+      asserts "that it can be passed conditionals" do
  105
+        template = rabl %{
  106
+          code(:foo, :if => lambda { |i| false }) { 'bar' }
  107
+        }
  108
+        template.render(Object.new).split("").sort
  109
+      end.equals "\x05\x00\x00\x00\x00".split("").sort
  110
+
  111
+    end
  112
+
  113
+    context "#child" do
  114
+
  115
+      asserts "that it can create a child node" do
  116
+        template = rabl %{
  117
+          object @user
  118
+          attribute :name
  119
+          child(@user) { attribute :city }
  120
+        }
  121
+        scope = Object.new
  122
+        scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA')
  123
+        template.render(scope).split("").sort
  124
+      end.equals "6\x00\x00\x00\x03user\x00+\x00\x00\x00\x02name\x00\x04\x00\x00\x00leo\x00\x03user\x00\x12\x00\x00\x00\x02city\x00\x03\x00\x00\x00LA\x00\x00\x00\x00".split("").sort
  125
+
  126
+      asserts "that it can create a child node with different key" do
  127
+        template = rabl %{
  128
+          object @user
  129
+          attribute :name
  130
+          child(@user => :person) { attribute :city }
  131
+        }
  132
+        scope = Object.new
  133
+        scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA')
  134
+        template.render(scope).split("").sort
  135
+      end.equals "8\x00\x00\x00\x03user\x00-\x00\x00\x00\x02name\x00\x04\x00\x00\x00leo\x00\x03person\x00\x12\x00\x00\x00\x02city\x00\x03\x00\x00\x00LA\x00\x00\x00\x00".split("").sort
  136
+    end
  137
+
  138
+    context "#glue" do
  139
+
  140
+      asserts "that it glues data from a child node" do
  141
+        template = rabl %{
  142
+          object @user
  143
+          attribute :name
  144
+          glue(@user) { attribute :city }
  145
+          glue(@user) { attribute :age  }
  146
+        }
  147
+        scope = Object.new
  148
+        scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA', :age => 12)
  149
+        template.render(scope).split("").sort
  150
+      end.equals "4\x00\x00\x00\x03user\x00)\x00\x00\x00\x02name\x00\x04\x00\x00\x00leo\x00\x02city\x00\x03\x00\x00\x00LA\x00\x10age\x00\f\x00\x00\x00\x00\x00".split("").sort
  151
+    end
  152
+
  153
+    teardown do
  154
+      Rabl.reset_configuration!
  155
+    end
  156
+  end
  157
+
  158
+  context "with bson_engine" do
  159
+    setup do
  160
+      class CustomEncodeEngine
  161
+        def self.serialize string
  162
+          42
  163
+        end
  164
+      end
  165
+
  166
+      Rabl.configure do |config|
  167
+        config.bson_engine = CustomEncodeEngine
  168
+      end
  169
+    end
  170
+
  171
+    asserts 'that it returns process by custom to_json' do
  172
+      template = rabl %q{
  173
+        object @user
  174
+      }
  175
+      scope = Object.new
  176
+      scope.instance_variable_set :@user, User.new
  177
+      template.render(scope)
  178
+    end.equals "42"
  179
+
  180
+    teardown do
  181
+      Rabl.reset_configuration!
  182
+    end
  183
+  end
  184
+
  185
+  context "without bson root" do
  186
+    setup do
  187
+      Rabl.configure do |config|
  188
+        config.include_bson_root = false
  189
+      end
  190
+    end
  191
+
  192
+    context "#object" do
  193
+
  194
+      asserts "that it sets data source" do
  195
+        template = rabl %q{
  196
+          object @user
  197
+        }
  198
+        scope = Object.new
  199
+        scope.instance_variable_set :@user, User.new
  200
+        template.render(scope)
  201
+      end.matches "\x05\x00\x00\x00\x00"
  202
+
  203
+      asserts "that it can set root node" do
  204
+        template = rabl %q{
  205
+          object @user => :person
  206
+        }
  207
+        scope = Object.new
  208
+        scope.instance_variable_set :@user, User.new
  209
+        template.render(scope)
  210
+      end.equals "\x05\x00\x00\x00\x00"
  211
+    end
  212
+
  213
+    context "#collection" do
  214
+
  215
+      asserts "that it sets object to be casted as a simple array" do
  216
+        template = rabl %{
  217
+          collection @users
  218
+        }
  219
+        scope = Object.new
  220
+        scope.instance_variable_set :@users, [User.new, User.new]
  221
+        template.render(scope).split("").sort
  222
+      end.equals "!\x00\x00\x00\x04users\x00\x15\x00\x00\x00\x030\x00\x05\x00\x00\x00\x00\x031\x00\x05\x00\x00\x00\x00\x00\x00".split("").sort
  223
+
  224
+      asserts "that it sets root node for objects" do
  225
+        template = rabl %{
  226
+          collection @users => :person
  227
+        }
  228
+        scope = Object.new
  229
+        scope.instance_variable_set :@users, [User.new, User.new]
  230
+        template.render(scope).split("").sort
  231
+      end.equals "\"\x00\x00\x00\x04person\x00\x15\x00\x00\x00\x030\x00\x05\x00\x00\x00\x00\x031\x00\x05\x00\x00\x00\x00\x00\x00".split("").sort
  232
+
  233
+    end
  234
+
  235
+    context "#attribute" do
  236
+
  237
+      asserts "that it adds an attribute or method to be included in output" do
  238
+        template = rabl %{
  239
+          object @user
  240
+          attribute :name
  241
+        }
  242
+        scope = Object.new
  243
+        scope.instance_variable_set :@user, User.new(:name => 'irvine')
  244
+        template.render(scope).split("").sort
  245
+      end.equals "\x16\x00\x00\x00\x02name\x00\a\x00\x00\x00irvine\x00\x00".split("").sort
  246
+
  247
+      asserts "that it can add attribute under a different key name through :as" do
  248
+        template = rabl %{
  249
+          object @user
  250
+          attribute :name, :as => 'city'
  251
+        }
  252
+        scope = Object.new
  253
+        scope.instance_variable_set :@user, User.new(:name => 'irvine')
  254
+        template.render(scope).split("").sort
  255
+      end.equals "\x16\x00\x00\x00\x02city\x00\a\x00\x00\x00irvine\x00\x00".split("").sort
  256
+
  257
+      asserts "that it can add attribute under a different key name through hash" do
  258
+        template = rabl %{
  259
+          object @user
  260
+          attribute :name => :city
  261
+        }
  262
+        scope = Object.new
  263
+        scope.instance_variable_set :@user, User.new(:name => 'irvine')
  264
+        template.render(scope).split("").sort
  265
+      end.equals "\x16\x00\x00\x00\x02city\x00\a\x00\x00\x00irvine\x00\x00".split("").sort
  266
+
  267
+    end
  268
+
  269
+    context "#code" do
  270
+
  271
+      asserts "that it can create an arbitraty code node" do
  272
+        template = rabl %{
  273
+          code(:foo) { 'bar' }
  274
+        }
  275
+        template.render(Object.new).split("").sort
  276
+      end.equals "\x12\x00\x00\x00\x02foo\x00\x04\x00\x00\x00bar\x00\x00".split("").sort
  277
+
  278
+      asserts "that it can be passed conditionals" do
  279
+        template = rabl %{
  280
+          code(:foo, :if => lambda { |i| false }) { 'bar' }
  281
+        }
  282
+        template.render(Object.new).split("").sort
  283
+      end.equals "\x05\x00\x00\x00\x00".split("").sort
  284
+
  285
+    end
  286
+
  287
+    context "#child" do
  288
+
  289
+      asserts "that it can create a child node" do
  290
+        template = rabl %{
  291
+          object @user
  292
+          attribute :name
  293
+          child(@user) { attribute :city }
  294
+        }
  295
+        scope = Object.new
  296
+        scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA')
  297
+        template.render(scope).split("").sort
  298
+      end.equals "+\x00\x00\x00\x02name\x00\x04\x00\x00\x00leo\x00\x03user\x00\x12\x00\x00\x00\x02city\x00\x03\x00\x00\x00LA\x00\x00\x00".split("").sort
  299
+
  300
+      asserts "that it can create a child node with different key" do
  301
+        template = rabl %{
  302
+          object @user
  303
+          attribute :name
  304
+          child(@user => :person) { attribute :city }
  305
+        }
  306
+        scope = Object.new
  307
+        scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA')
  308
+        template.render(scope).split("").sort
  309
+      end.equals "-\x00\x00\x00\x02name\x00\x04\x00\x00\x00leo\x00\x03person\x00\x12\x00\x00\x00\x02city\x00\x03\x00\x00\x00LA\x00\x00\x00".split("").sort
  310
+    end
  311
+
  312
+    context "#glue" do
  313
+
  314
+      asserts "that it glues data from a child node" do
  315
+        template = rabl %{
  316
+          object @user
  317
+          attribute :name
  318
+          glue(@user) { attribute :city }
  319
+          glue(@user) { attribute :age  }
  320
+        }
  321
+        scope = Object.new
  322
+        scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA', :age => 12)
  323
+        template.render(scope).split("").sort
  324
+      end.equals ")\x00\x00\x00\x02name\x00\x04\x00\x00\x00leo\x00\x02city\x00\x03\x00\x00\x00LA\x00\x10age\x00\f\x00\x00\x00\x00".split("").sort
  325
+    end
  326
+
  327
+    teardown do
  328
+      Rabl.reset_configuration!
  329
+    end
  330
+  end
  331
+end
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.