rabl 0.9.3 → 0.9.4.pre1

Sign up to get free protection for your applications and to get access to all the features.
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