rabl 0.9.3 → 0.9.4.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MjcwOGMyNWMwNDhjYzlkN2ZkMTg3ZjRlMjgwMzdiYTliNTQwOWE3NA==
5
- data.tar.gz: !binary |-
6
- N2FjZmZkNjFhMmVhMTY4NjAxNDEyNGZmN2ZkMzUyMzJlMmYxZWViZg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- YjQ1YmM1Y2FkZGFjYmYxYzJmMGQyYmI1Y2MzZjkwNGJmMmNhMDU2NzFjYjZi
10
- ZmZhYTRmZGNiZmFmOTkxMjY2OWZkZjQ2OTRhMmNkZDlmMmZiMjQ5MTMzNjdi
11
- MDA4NmE4ZmNmYjA4Njk3MDcyM2QyMDI4OGJjYzdiZmRjNTNhMWY=
12
- data.tar.gz: !binary |-
13
- Mjk5MGY5YmZlNTZkMjQ0YjUwNjdmZDlmYmU4NjNjNDYzNDMwODliMzQwNjQy
14
- MGI2NGJlMDQ4MjhmOWIxNTRiYmEyZjgxZTM0NTE1YTcxYmNjMDQ3Y2I3OTc5
15
- MmRkZWU5ODdlZGM5YTdiOTU4YzQ3NDZjODYxMmI1MDhjYzEzOGM=
2
+ SHA1:
3
+ metadata.gz: 1866c412279ffb2db8142893bab3ea5f898aad3b
4
+ data.tar.gz: 0dd7d7cd23cef1401f1e84b65f4bbd3ec9438e08
5
+ SHA512:
6
+ metadata.gz: 730240cb3efea4af23359f5a11a5e022f83355b00e3ff58c6bf90a44a45f54d84ad6ea263617d6d0bdd5988cfae8ecd5b06150e96ac23acf012cf55d3cf1cfbb
7
+ data.tar.gz: 51942438bcba8d05ec2029b9e41a672ac438281c28b3dc9246aa02a398b2e1ba79abc8c83b4442d12f4f015f28a517e86a7629e78187311865e997931550c0d5
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ Gemfile.lock
5
5
  pkg/*
6
6
  fixtures/rails2/log/*.log
7
7
  tags
8
+ .idea
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.9.4.pre1 (March 30th)
4
+
5
+ * NEW #527 Add configuration excluding empty values in collections (@addbrick)
6
+ * FIX #516 Set default root_object lazily (@DouweM)
7
+ * FIX #540 Fix cache digest in Rails 4.1 (@huoxito)
8
+ * FIX #534 Bug with management of empty string values (@nickkov89)
9
+ * FIX #519 JSON in README (@shirish4you)
10
+ * NEW #514 Add configuration to exclude nil values (@oharsta)
11
+
3
12
  ## 0.9.3 (December 5th)
4
13
 
5
14
  * FIX Send engine options through from render call (Thanks @bhicks)
data/README.md CHANGED
@@ -105,8 +105,8 @@ Which would output the following JSON or XML when visiting `http://localhost:300
105
105
  ```js
106
106
  [{ "post" :
107
107
  {
108
- "id" : 5, title: "...", subject: "...",
109
- "user" : { full_name : "..." },
108
+ "id" : 5, "title": "...", "subject": "...",
109
+ "user" : { "full_name" : "..." },
110
110
  "read" : true
111
111
  }
112
112
  }]
@@ -143,10 +143,13 @@ Rabl.configure do |config|
143
143
  # config.view_paths = []
144
144
  # config.raise_on_missing_attribute = true # Defaults to false
145
145
  # config.replace_nil_values_with_empty_strings = true # Defaults to false
146
+ # config.replace_empty_string_values_with_nil = true # Defaults to false
147
+ # config.exclude_nil_values = true # Defaults to false
148
+ # config.exclude_empty_values_in_collections = true # Defaults to false
146
149
  end
147
150
  ```
148
151
 
149
- Each option specifies behavior related to RABL's output.
152
+ Each option specifies behavior related to RABL's output.
150
153
 
151
154
  If `include_json_root` is disabled that removes the root node for each root object in the output, and `enable_json_callbacks` enables support for 'jsonp' style callback
152
155
  output if the incoming request has a 'callback' parameter.
@@ -180,6 +183,10 @@ production code is not recommended.
180
183
 
181
184
  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.
182
185
 
186
+ If `exclude_nil_values` is set to `true`, all values that are `nil` and would normally be displayed as `null` in the response are not included in the response.
187
+
188
+ if `exclude_empty_values_in_collections` is set to `true`, all vaules in a collection that are `{}` and would normally be displayed as `{}` in the response are not included in the response.
189
+
183
190
  If you wish to use [oj](https://github.com/ohler55/oj) as
184
191
  the primary JSON encoding engine simply add that to your Gemfile:
185
192
 
data/lib/rabl/builder.rb CHANGED
@@ -44,7 +44,9 @@ module Rabl
44
44
 
45
45
  wrap_result(options[:root_name])
46
46
 
47
- replace_nil_values if Rabl.configuration.replace_nil_values_with_empty_strings
47
+ replace_nil_values if Rabl.configuration.replace_nil_values_with_empty_strings
48
+ replace_empty_string_values if Rabl.configuration.replace_empty_string_values_with_nil_values
49
+ remove_nil_values if Rabl.configuration.exclude_nil_values
48
50
 
49
51
  # Return Results
50
52
  @_root_name ? { @_root_name => @_result } : @_result
@@ -57,6 +59,20 @@ module Rabl
57
59
  end
58
60
  end
59
61
 
62
+ def replace_empty_string_values
63
+ @_result = @_result.inject({}) do |hash, (k, v)|
64
+ hash[k] = (!v.nil? && v != "") ? v : nil
65
+ hash
66
+ end
67
+ end
68
+
69
+ def remove_nil_values
70
+ @_result = @_result.inject({}) do |hash, (k, v)|
71
+ hash[k] = v unless v.nil?
72
+ hash
73
+ end
74
+ end
75
+
60
76
  def wrap_result(root_name)
61
77
  if root_name.present?
62
78
  @_root_name = root_name
@@ -48,31 +48,37 @@ module Rabl
48
48
  attr_accessor :raise_on_missing_attribute
49
49
  attr_accessor :perform_caching
50
50
  attr_accessor :replace_nil_values_with_empty_strings
51
+ attr_accessor :replace_empty_string_values_with_nil_values
52
+ attr_accessor :exclude_nil_values
53
+ attr_accessor :exclude_empty_values_in_collections
51
54
 
52
55
  DEFAULT_XML_OPTIONS = { :dasherize => true, :skip_types => false }
53
56
 
54
57
  def initialize
55
- @include_json_root = true
56
- @include_child_root = true
57
- @include_msgpack_root = true
58
- @include_plist_root = true
59
- @include_xml_root = false
60
- @include_bson_root = true
61
- @enable_json_callbacks = false
62
- @bson_check_keys = false
63
- @bson_move_id = false
64
- @json_engine = nil
65
- @msgpack_engine = nil
66
- @bson_engine = nil
67
- @plist_engine = nil
68
- @xml_options = {}
69
- @cache_sources = false
70
- @cache_all_output = false
71
- @escape_all_output = false
72
- @view_paths = []
73
- @cache_engine = Rabl::CacheEngine.new
74
- @perform_caching = false
75
- @replace_nil_values_with_empty_strings = false
58
+ @include_json_root = true
59
+ @include_child_root = true
60
+ @include_msgpack_root = true
61
+ @include_plist_root = true
62
+ @include_xml_root = false
63
+ @include_bson_root = true
64
+ @enable_json_callbacks = false
65
+ @bson_check_keys = false
66
+ @bson_move_id = false
67
+ @json_engine = nil
68
+ @msgpack_engine = nil
69
+ @bson_engine = nil
70
+ @plist_engine = nil
71
+ @xml_options = {}
72
+ @cache_sources = false
73
+ @cache_all_output = false
74
+ @escape_all_output = false
75
+ @view_paths = []
76
+ @cache_engine = Rabl::CacheEngine.new
77
+ @perform_caching = false
78
+ @replace_nil_values_with_empty_strings = false
79
+ @replace_empty_string_values_with_nil_values = false
80
+ @exclude_nil_values = false
81
+ @exclude_empty_values_in_collections = false
76
82
  end
77
83
 
78
84
  # @return The JSON engine used to encode Rabl templates into JSON
data/lib/rabl/digestor.rb CHANGED
@@ -2,17 +2,30 @@ module Rabl
2
2
  class Digestor < ActionView::Digestor
3
3
  # Override the original digest function to ignore partial which
4
4
  # rabl doesn't use the Rails conventional _ symbol.
5
- def self.digest(name, format, finder, options = {})
6
- cache_key = [name, format] + Array.wrap(options[:dependencies])
7
- @@cache[cache_key.join('.')] ||= begin
8
- Digestor.new(name, format, finder, options).digest
5
+ if Rails.version.to_s >= '4.1'
6
+ def self.digest(options = {})
7
+ cache_key = [options[:name]] + Array.wrap(options[:dependencies])
8
+ @@cache[cache_key.join('.')] ||= begin
9
+ Digestor.new({ name: options[:name], finder: options[:finder] }.merge!(options)).digest
10
+ end
11
+ end
12
+ else
13
+ def self.digest(name, format, finder, options = {})
14
+ cache_key = [name, format] + Array.wrap(options[:dependencies])
15
+ @@cache[cache_key.join('.')] ||= begin
16
+ Digestor.new(name, format, finder, options).digest
17
+ end
9
18
  end
10
19
  end
11
20
 
12
21
  private
13
22
  def dependency_digest
14
23
  template_digests = dependencies.collect do |template_name|
15
- Digestor.digest(template_name, format, finder)
24
+ if Rails.version.to_s >= '4.1'
25
+ Digestor.digest(name: template_name, finder: finder)
26
+ else
27
+ Digestor.digest(template_name, format, finder)
28
+ end
16
29
  end
17
30
 
18
31
  (template_digests + injected_dependencies).join("-")
data/lib/rabl/engine.rb CHANGED
@@ -27,15 +27,12 @@ module Rabl
27
27
  locals.each { |k,v| instance_variable_set(:"@#{k}", v) }
28
28
  @_options[:scope] = @_scope
29
29
  @_options[:format] ||= self.request_format
30
- data = locals[:object].nil? ? self.default_object : locals[:object]
31
- @_data_object = data_object(data)
32
- @_data_name = @_options[:object_root_name] || data_name(data)
33
30
  if @_options[:source_location]
34
31
  instance_eval(@_source, @_options[:source_location]) if @_source.present?
35
32
  else # without source location
36
33
  instance_eval(@_source) if @_source.present?
37
34
  end
38
- instance_exec(@_data_object, &block) if block_given?
35
+ instance_exec(root_object, &block) if block_given?
39
36
  cache_results { self.send("to_" + @_options[:format].to_s, @_options) }
40
37
  end
41
38
 
@@ -43,14 +40,16 @@ module Rabl
43
40
  # to_hash(:root => true, :child_root => true)
44
41
  def to_hash(options={})
45
42
  options = options.merge(@_options)
46
- data = @_data_object
43
+ data = root_object
47
44
  builder = Rabl::Builder.new(options)
48
- options[:root_name] = determine_object_root(@_data_object, @_data_name, options[:root])
45
+ options[:root_name] = determine_object_root(data, root_name, options[:root])
49
46
 
50
47
  if is_object?(data) || !data # object @user
51
48
  builder.build(data, options)
52
49
  elsif is_collection?(data) # collection @users
53
- data.map { |object| builder.build(object, options) }
50
+ result = data.map { |object| builder.build(object, options) }
51
+ result = result.map(&:presence).compact if Rabl.configuration.exclude_empty_values_in_collections
52
+ result
54
53
  end
55
54
  end
56
55
 
@@ -91,7 +90,7 @@ module Rabl
91
90
  include_root = Rabl.configuration.include_xml_root
92
91
  include_child_root = include_root && Rabl.configuration.include_child_root
93
92
  options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
94
- xml_options = Rabl.configuration.default_xml_options.merge(:root => collection_root_name || @_data_name)
93
+ xml_options = Rabl.configuration.default_xml_options.merge(:root => collection_root_name || root_name)
95
94
  result = to_hash(options)
96
95
  result.to_xml(xml_options)
97
96
  end
@@ -104,8 +103,8 @@ module Rabl
104
103
  options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
105
104
  result = if collection_root_name
106
105
  { collection_root_name => to_hash(options) }
107
- elsif is_collection?(@_data_object) && @_data_object.is_a?(Array)
108
- { @_data_name => to_hash(options) }
106
+ elsif is_collection?(root_object) && root_object.is_a?(Array)
107
+ { root_name => to_hash(options) }
109
108
  else
110
109
  to_hash(options)
111
110
  end
@@ -126,7 +125,19 @@ module Rabl
126
125
  # Can be the collection or the object depending on topic assigned
127
126
  # root_object => @user
128
127
  def root_object
129
- @_data_object
128
+ return @_data_object if defined?(@_data_object)
129
+
130
+ data = @_locals[:object].nil? ? self.default_object : @_locals[:object]
131
+ @_data_object = data_object(data)
132
+ end
133
+
134
+ def root_name
135
+ return @_data_name if defined?(@_data_name)
136
+
137
+ @_data_name = @_options[:object_root_name] || begin
138
+ data = @_locals[:object].nil? ? root_object : @_locals[:object]
139
+ data_name(data)
140
+ end
130
141
  end
131
142
 
132
143
  # Sets the object as a collection casted to a simple array
@@ -149,7 +160,7 @@ module Rabl
149
160
  # cache 'user', expires_in: 1.hour
150
161
  # options is passed through to the cache store
151
162
  def cache(key = nil, options = nil)
152
- key ||= @_data_object # if called but missing, use object
163
+ key ||= root_object # if called but missing, use object
153
164
  @_cache = [key, options]
154
165
  end
155
166
 
@@ -288,10 +299,17 @@ module Rabl
288
299
 
289
300
  def cache_key_with_digest(cache_key)
290
301
  template = @_options[:template] || @virtual_path
302
+
303
+ if Rails.version.to_s >= '4.1'
304
+ digested = Digestor.digest(name: template, finder: lookup_context)
305
+ else
306
+ digested = Digestor.digest(template, :rabl, lookup_context)
307
+ end
308
+
291
309
  Array(cache_key) + [
292
310
  @_options[:root_name],
293
311
  @_options[:format],
294
- Digestor.digest(template, :rabl, lookup_context)
312
+ digested
295
313
  ]
296
314
  rescue NameError => e # Handle case where lookup_context doesn't exist
297
315
  raise e unless e.message =~ /lookup_context/
data/lib/rabl/helpers.rb CHANGED
@@ -27,9 +27,12 @@ module Rabl
27
27
  return unless data_token # nil or false
28
28
  return data_token.values.first if data_token.is_a?(Hash) # @user => :user
29
29
  data = data_object(data_token)
30
- if is_collection?(data) && data.respond_to?(:first) # data is a collection
30
+ if is_collection?(data) # data is a collection
31
31
  object_name = data.table_name if data.respond_to?(:table_name)
32
- object_name ||= data_name(data.first).to_s.pluralize if data.first.present?
32
+ if !object_name && data.respond_to?(:first)
33
+ first = data.first
34
+ object_name = data_name(first).to_s.pluralize if first.present?
35
+ end
33
36
  object_name ||= data_token if data_token.is_a?(Symbol)
34
37
  object_name
35
38
  elsif is_object?(data) # data is an object
data/lib/rabl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rabl
2
- VERSION = "0.9.3"
2
+ VERSION = "0.9.4.pre1"
3
3
  end
data/test/builder_test.rb CHANGED
@@ -55,6 +55,42 @@ context "Rabl::Builder" do
55
55
  Rabl.configuration.replace_nil_values_with_empty_strings = false
56
56
  end
57
57
  end
58
+
59
+ context "when empty string values are replaced with nil values" do
60
+ setup do
61
+ Rabl.configuration.replace_empty_string_values_with_nil_values = true
62
+ builder({ :attributes => { :name => {} } })
63
+ end
64
+
65
+ asserts "that nil is returned as the value" do
66
+ topic.build(User.new(:name => ""))
67
+ end.equivalent_to({ :name => nil })
68
+
69
+ asserts "that it handles existing nil values correctly" do
70
+ topic.build(User.new(:name => nil))
71
+ end.equivalent_to({ :name => nil })
72
+
73
+ asserts "that it handles existing non nil values correctly" do
74
+ topic.build(User.new(:name => 10))
75
+ end.equivalent_to({ :name => 10 })
76
+
77
+ teardown do
78
+ Rabl.configuration.replace_empty_string_values_with_nil_values = false
79
+ end
80
+ end
81
+
82
+ context "when nil values are excluded" do
83
+ setup do
84
+ Rabl.configuration.exclude_nil_values = true
85
+ builder({ :attributes => { :name => {} } })
86
+ end
87
+ asserts "that an nil attribute is not returned" do
88
+ topic.build(User.new(:name => nil))
89
+ end.equivalent_to({ })
90
+ teardown do
91
+ Rabl.configuration.exclude_nil_values = false
92
+ end
93
+ end
58
94
  end
59
95
 
60
96
  context "#attribute" do
@@ -14,6 +14,9 @@ context 'Rabl::Configuration' do
14
14
  asserts(:json_engine).equals { json_engine }
15
15
  asserts(:cache_engine).is_a?(Rabl::CacheEngine)
16
16
  asserts(:replace_nil_values_with_empty_strings).equals false
17
+ asserts(:replace_empty_string_values_with_nil_values).equals false
18
+ asserts(:exclude_nil_values).equals false
19
+ asserts(:exclude_empty_values_in_collections).equals false
17
20
  end
18
21
 
19
22
  context 'custom JSON engine configured as Symbol' do
@@ -55,4 +58,34 @@ context 'Rabl::Configuration' do
55
58
 
56
59
  asserts(:replace_nil_values_with_empty_strings).equals true
57
60
  end # replace nil values with empty strings
61
+
62
+ context 'replace empty string values with nil values' do
63
+ setup do
64
+ Rabl.configure do |c|
65
+ c.replace_empty_string_values_with_nil_values = true
66
+ end
67
+ end
68
+
69
+ asserts(:replace_empty_string_values_with_nil_values).equals true
70
+ end # replace empty string values with nil values
71
+
72
+ context 'exclude nil values' do
73
+ setup do
74
+ Rabl.configure do |c|
75
+ c.exclude_nil_values = true
76
+ end
77
+ end
78
+
79
+ asserts(:exclude_nil_values).equals true
80
+ end # exclude nil values
81
+
82
+ context 'exclude empty values in collections' do
83
+ setup do
84
+ Rabl.configure do |c|
85
+ c.exclude_empty_values_in_collections = true
86
+ end
87
+ end
88
+
89
+ asserts(:exclude_empty_values_in_collections).equals true
90
+ end # exclude empty values in collections
58
91
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Esquenazi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-06 00:00:00.000000000 Z
11
+ date: 2014-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.3.14
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 2.3.14
27
27
  - !ruby/object:Gem::Dependency
@@ -56,42 +56,42 @@ dependencies:
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ! '>='
59
+ - - '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>='
66
+ - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: tilt
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ! '>='
73
+ - - '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ! '>='
80
+ - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: oj
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ! '>='
87
+ - - '>='
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ! '>='
94
+ - - '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
@@ -126,14 +126,14 @@ dependencies:
126
126
  name: plist
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ! '>='
129
+ - - '>='
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ! '>='
136
+ - - '>='
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  description: General ruby templating with json, bson, xml and msgpack support
@@ -456,17 +456,17 @@ require_paths:
456
456
  - lib
457
457
  required_ruby_version: !ruby/object:Gem::Requirement
458
458
  requirements:
459
- - - ! '>='
459
+ - - '>='
460
460
  - !ruby/object:Gem::Version
461
461
  version: '0'
462
462
  required_rubygems_version: !ruby/object:Gem::Requirement
463
463
  requirements:
464
- - - ! '>='
464
+ - - '>'
465
465
  - !ruby/object:Gem::Version
466
- version: '0'
466
+ version: 1.3.1
467
467
  requirements: []
468
468
  rubyforge_project: rabl
469
- rubygems_version: 2.0.7
469
+ rubygems_version: 2.0.6
470
470
  signing_key:
471
471
  specification_version: 4
472
472
  summary: General ruby templating with json, bson, xml and msgpack support