Skip to content

Commit

Permalink
feature: extract! api for getting attributes from object (#32)
Browse files Browse the repository at this point in the history
* feature: extract! api for getting attributes from object

* add key transformation to extract! syntax
  • Loading branch information
kortirso authored Aug 2, 2024
1 parent f671628 commit 113e163
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 0 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,33 @@ The difference between the block form and inline form is
2. The inline form is considered a leaf node, and you can only [search](#traversing)
for internal nodes.

### json.extract!
Extracts attributes from object or hash in 1 line

```ruby
# without extract!
json.id user.id
json.email user.email
json.firstName user.first_name

# with extract!
json.extract! user, :id, :email, :first_name

# => {"id" => 1, "email" => "email@gmail.com", "first_name" => "user"}

# with extract! with key transformation
json.extract! user, :id, [:first_name, :firstName], [:last_name, :lastName]

# => {"id" => 1, "firstName" => "user", "lastName" => "last"}
```

The inline form defines object and attributes

| Parameter | Notes |
| :--- | :--- |
| object | An object |
| attributes | A list of attributes |

### json.array!
Generates an array of json objects.

Expand Down
1 change: 1 addition & 0 deletions lib/props_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class << self
self.template_lookup_options = {handlers: [:props]}

delegate :result!, :array!,
:extract!,
:deferred!,
:fragments!,
:set_block_content!,
Expand Down
22 changes: 22 additions & 0 deletions lib/props_template/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,28 @@ def array!(collection, options = {})
nil
end

# json.id item.id
# json.value item.value
#
# json.extract! item, :id, :value
#
# with key transformation
# json.extract! item, :id, [:first_name, :firstName]
def extract!(object, *values)
values.each do |value|
key, attribute = if value.is_a?(Array)
[value[1], value[0]]
else
[value, value]
end

set!(
key,
object.is_a?(Hash) ? object.fetch(attribute) : object.public_send(attribute)
)
end
end

def result!
if @scope.nil?
@stream.push_object
Expand Down
49 changes: 49 additions & 0 deletions spec/props_template_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,53 @@
}.to raise_error(Props::InvalidScopeForArrayError)
end
end

context "extract!" do
it "extracts values for hash" do
object = { :foo => "bar", "bar" => "foo", :wiz => "wiz" }

json = Props::Base.new
json.extract! object, :foo, "bar"
attrs = json.result!.strip

expect(attrs).to eql_json({
foo: "bar",
bar: "foo"
})
end

it "extracts values for hash with key transformation" do
object = { :foo => "bar", "bar_bar" => "foo", :wiz => "wiz" }

json = Props::Base.new
json.extract! object, :foo, ["bar_bar", "barBar"]
attrs = json.result!.strip

expect(attrs).to eql_json({
foo: "bar",
barBar: "foo"
})
end

it "extracts values for object" do
class FooBar
def foo
"bar"
end

def bar
"foo"
end
end

json = Props::Base.new
json.extract! FooBar.new, :foo, "bar"
attrs = json.result!.strip

expect(attrs).to eql_json({
foo: "bar",
bar: "foo"
})
end
end
end

0 comments on commit 113e163

Please sign in to comment.