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

Implement primitive! method #527

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,20 @@ json.partial! 'sub_template', locals: { user: user }
json.partial! 'sub_template', user: user
```

You can explicitly make Jbuilder object return a primitive value:

You can explicitly make Jbuilder object return null if you want:
``` ruby
json.extract! @post, :id, :title, :content, :published_at
json.author do
if @post.pseudonymous?
json.primitive! @post.author_pseudonym
else
json.first_name @post.author_first_name
json.last_name @post.author_last_name
end
```

Returning null is also possible:

``` ruby
json.extract! @post, :id, :title, :content, :published_at
Expand Down
15 changes: 15 additions & 0 deletions lib/jbuilder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,17 @@ def call(object, *attributes, &block)
end
end

# Returns a primitive JSON
# Example:
#
# json.primitive! "hello"
#
# "hello"
def primitive!(value)
raise PrimitiveError.build(value) unless _is_primitive?(value)
@attributes = value
end

# Returns the nil JSON.
def nil!
@attributes = nil
Expand Down Expand Up @@ -354,6 +365,10 @@ def _is_collection?(object)
_object_respond_to?(object, :map, :count) && NON_ENUMERABLES.none?{ |klass| klass === object }
end

def _is_primitive?(value)
(value.is_a? ::String) || (value.is_a? ::Numeric) || value == true || value == false || value.nil?
end

def _blank?(value=@attributes)
BLANK == value
end
Expand Down
7 changes: 7 additions & 0 deletions lib/jbuilder/errors.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
require 'jbuilder/jbuilder'

class Jbuilder
class PrimitiveError < ::StandardError
def self.build(value)
message = "Can't use #{value.inspect} as primitive"
new(message)
end
end

class NullError < ::NoMethodError
def self.build(key)
message = "Failed to add #{key.to_s.inspect} property to null object"
Expand Down
73 changes: 73 additions & 0 deletions test/jbuilder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,57 @@ class JbuilderTest < ActiveSupport::TestCase
Jbuilder.send(:class_variable_set, '@@ignore_nil', false)
end

test 'primitive! with String value' do
result = jbuild do |json|
json.primitive! 'hello'
end

assert_equal 'hello', result
end

test 'primitive! with Numeric value' do
result = jbuild do |json|
json.primitive! 13.37
end

assert_equal 13.37, result
end

test 'primitive! with true value' do
result = jbuild do |json|
json.primitive! true
end

assert_equal true, result
end

test 'primitive! with false value' do
result = jbuild do |json|
json.primitive! false
end

assert_equal false, result
end

test 'primitive! with nil value' do
result = jbuild do |json|
json.primitive! nil
end

assert_equal nil, result
end

test 'primitive! in an empty block' do
result = jbuild do |json|
json.author do
json.primitive! 'David Heinemeier Hansson'
end
end

assert result.key?('author')
assert_equal 'David Heinemeier Hansson', result['author']
end

test 'nil!' do
result = jbuild do |json|
json.key 'value'
Expand Down Expand Up @@ -871,6 +922,14 @@ class JbuilderTest < ActiveSupport::TestCase
assert !attributes.present?
end

test 'throws PrimitiveError when trying to use hash as primitive' do
assert_raise Jbuilder::PrimitiveError do
jbuild do |json|
json.primitive!({})
end
end
end

test 'throws ArrayError when trying to add a key to an array' do
assert_raise Jbuilder::ArrayError do
jbuild do |json|
Expand Down Expand Up @@ -930,6 +989,20 @@ class JbuilderTest < ActiveSupport::TestCase
end
end

test "throws MergeError when trying to replace non-empty block with primitive" do
assert_raise Jbuilder::MergeError do
jbuild do |json|
json.author do
json.name 'David'
end

json.author do
json.primitive! 'David Heinemeier Hansson'
end
end
end
end

if RUBY_VERSION >= "2.2.10"
test "respects JSON encoding customizations" do
# Active Support overrides Time#as_json for custom formatting.
Expand Down