diff --git a/README.md b/README.md index 52317947..2e186a21 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ Rabl.configure do |config| # config.xml_options = { :dasherize => true, :skip_types => false } # config.view_paths = [] # config.raise_on_missing_attribute = true # Defaults to false + # config.replace_nil_values_with_empty_strings = true # Defaults to false end ``` @@ -171,6 +172,8 @@ attempts to render an attribute that does not exist. Otherwise, the attribute wi Setting this to true during development may help increase the robustness of your code, but using `true` in production code is not recommended. +If `replace_nil_values_with_empty_strings` is set to `true`, all values that are `nil` and would normally be displayed as `null` in the response are converted to empty strings. + If you wish to use [oj](https://github.com/ohler55/oj) as the primary JSON encoding engine simply add that to your Gemfile: diff --git a/lib/rabl/builder.rb b/lib/rabl/builder.rb index 97b9ddc5..4fea85a9 100644 --- a/lib/rabl/builder.rb +++ b/lib/rabl/builder.rb @@ -57,6 +57,14 @@ def compile_hash(options={}) @_root_name = nil end + # Replace nil values with empty strings if configured + if Rabl.configuration.replace_nil_values_with_empty_strings + @_result = @_result.inject({}) do |hash, (k, v)| + hash[k] = v.nil? ? '' : v + hash + end + end + # Return Results @_root_name ? { @_root_name => @_result } : @_result end diff --git a/lib/rabl/configuration.rb b/lib/rabl/configuration.rb index 59fc7361..f62611da 100644 --- a/lib/rabl/configuration.rb +++ b/lib/rabl/configuration.rb @@ -47,30 +47,32 @@ class Configuration attr_accessor :cache_engine attr_accessor :raise_on_missing_attribute attr_accessor :perform_caching + attr_accessor :replace_nil_values_with_empty_strings DEFAULT_XML_OPTIONS = { :dasherize => true, :skip_types => false } def initialize - @include_json_root = true - @include_child_root = true - @include_msgpack_root = true - @include_plist_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 - @plist_engine = nil - @xml_options = {} - @cache_sources = false - @cache_all_output = false - @escape_all_output = false - @view_paths = [] - @cache_engine = Rabl::CacheEngine.new - @perform_caching = false + @include_json_root = true + @include_child_root = true + @include_msgpack_root = true + @include_plist_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 + @plist_engine = nil + @xml_options = {} + @cache_sources = false + @cache_all_output = false + @escape_all_output = false + @view_paths = [] + @cache_engine = Rabl::CacheEngine.new + @perform_caching = false + @replace_nil_values_with_empty_strings = false end # @return The JSON engine used to encode Rabl templates into JSON diff --git a/test/builder_test.rb b/test/builder_test.rb index 9b8060fb..052a4d85 100644 --- a/test/builder_test.rb +++ b/test/builder_test.rb @@ -42,6 +42,19 @@ topic.build(User.new, :root => false) end.equivalent_to({ :name => "rabl" }) end + + context "when nil values are replaced with empty strings" do + setup do + Rabl.configuration.replace_nil_values_with_empty_strings = true + builder({ :attributes => { :name => {} } }) + end + asserts "that an empty string is returned as the value" do + topic.build(User.new(:name => nil)) + end.equivalent_to({ :name => "" }) + teardown do + Rabl.configuration.replace_nil_values_with_empty_strings = false + end + end end context "#attribute" do diff --git a/test/configuration_test.rb b/test/configuration_test.rb index e44d5c91..8fe7c016 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -13,6 +13,7 @@ asserts(:view_paths).equals [] asserts(:json_engine).equals { json_engine } asserts(:cache_engine).is_a?(Rabl::CacheEngine) + asserts(:replace_nil_values_with_empty_strings).equals false end context 'custom JSON engine configured as Symbol' do @@ -44,4 +45,14 @@ asserts(:raise_on_missing_attribute).equals true end # raise on missing + + context 'replace nil values with empty strings' do + setup do + Rabl.configure do |c| + c.replace_nil_values_with_empty_strings = true + end + end + + asserts(:replace_nil_values_with_empty_strings).equals true + end # replace nil values with empty strings end diff --git a/test/models/user.rb b/test/models/user.rb index 5dfc1a72..e0a12126 100644 --- a/test/models/user.rb +++ b/test/models/user.rb @@ -10,12 +10,10 @@ class User DEFAULT_HOBBIES = ['Photography'] def initialize(attributes={}) - self.age = attributes[:age] || DEFAULT_AGE - self.city = attributes[:city] || DEFAULT_CITY - self.name = attributes[:name] || DEFAULT_NAME - self.first = attributes[:first] || DEFAULT_FIRST - self.float = attributes[:float] || DEFAULT_FLOAT - self.hobbies = (attributes[:hobbies] || DEFAULT_HOBBIES).map { |h| Hobby.new(h) } + %w(age city name first float hobbies).each do |attr| + self.send "#{attr}=", (attributes.has_key?(attr.to_sym) ? attributes[attr.to_sym] : self.class.const_get("DEFAULT_#{attr.upcase}")) + end + self.hobbies = self.hobbies.map { |h| Hobby.new(h) } end end