Skip to content
Merged
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
23 changes: 14 additions & 9 deletions lib/structured_params/params.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,20 @@ def errors
end

# Convert structured objects to Hash and get attributes
#: (symbolize: true) -> Hash[Symbol, untyped]
#: (symbolize: false) -> Hash[String, untyped]
def attributes(symbolize: false)
#: (symbolize: true, compact: false) -> Hash[Symbol, untyped]
#: (symbolize: false, compact: false) -> Hash[String, untyped]
#: (symbolize: true, compact: true) -> Hash[Symbol, untyped]
#: (symbolize: false, compact: true) -> Hash[String, untyped]
def attributes(symbolize: false, compact: false)
attrs = super()

self.class.structured_attributes.each_key do |name|
value = attrs[name.to_s]
attrs[name.to_s] = serialize_structured_value(value)
attrs[name.to_s] = serialize_structured_value(value, compact: compact)
end

symbolize ? attrs.deep_symbolize_keys : attrs
result = symbolize ? attrs.deep_symbolize_keys : attrs
compact ? result.compact : result
end

private
Expand Down Expand Up @@ -151,13 +154,15 @@ def format_error_path(attr_name, index = nil)
end

# Serialize structured values
#: (untyped) -> untyped
def serialize_structured_value(value)
#: (bool, compact: false) -> untyped
#: (bool, compact: true) -> untyped
def serialize_structured_value(value, compact: false)
case value
when Array
value.map { |item| item.attributes(symbolize: false) }
result = value.map { |item| item.attributes(symbolize: false, compact: compact) }
compact ? result.compact : result
when StructuredParams::Params
value.attributes(symbolize: false)
value.attributes(symbolize: false, compact: compact)
else
value
end
Expand Down
18 changes: 12 additions & 6 deletions sig/structured_params/params.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ module StructuredParams
def errors: () -> ::StructuredParams::Errors

# Convert structured objects to Hash and get attributes
# : (symbolize: true) -> Hash[Symbol, untyped]
# : (symbolize: false) -> Hash[String, untyped]
def attributes: (symbolize: true) -> Hash[Symbol, untyped]
| (symbolize: false) -> Hash[String, untyped]
# : (symbolize: true, compact: false) -> Hash[Symbol, untyped]
# : (symbolize: false, compact: false) -> Hash[String, untyped]
# : (symbolize: true, compact: true) -> Hash[Symbol, untyped]
# : (symbolize: false, compact: true) -> Hash[String, untyped]
def attributes: (symbolize: true, compact: false) -> Hash[Symbol, untyped]
| (symbolize: false, compact: false) -> Hash[String, untyped]
| (symbolize: true, compact: true) -> Hash[Symbol, untyped]
| (symbolize: false, compact: true) -> Hash[String, untyped]

private

Expand Down Expand Up @@ -70,8 +74,10 @@ module StructuredParams
def format_error_path: (Symbol, Integer?) -> String

# Serialize structured values
# : (untyped) -> untyped
def serialize_structured_value: (untyped) -> untyped
# : (bool, compact: false) -> untyped
# : (bool, compact: true) -> untyped
def serialize_structured_value: (bool, compact: false) -> untyped
| (bool, compact: true) -> untyped

# Integrate structured parameter errors into parent errors
# : (untyped, String) -> void
Expand Down
87 changes: 86 additions & 1 deletion spec/params_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,12 @@
end

describe '#attributes' do
subject(:attributes) { build(:user_parameter, **user_param_attributes).attributes(symbolize: symbolize) }
subject(:attributes) do
build(:user_parameter, **user_param_attributes).attributes(symbolize: symbolize, compact: compact)
end

let(:user_param_attributes) { attributes_for(:user_parameter) }
let(:compact) { false }

context 'when symbolize: false' do
let(:symbolize) { false }
Expand All @@ -175,6 +178,88 @@

it { is_expected.to eq user_param_attributes.deep_symbolize_keys }
end

context 'with compact: true' do
let(:symbolize) { false }
let(:compact) { true }

context 'with nil values' do
let(:user_param_attributes) do
{
name: 'Tanaka Taro',
email: nil,
age: 30,
address: {
postal_code: '123-4567',
prefecture: nil,
city: 'Shibuya-ku',
street: nil
},
hobbies: [
{ name: 'programming', level: 3, years_experience: nil },
{ name: nil, level: 2, years_experience: 5 }
],
tags: %w[Ruby Rails Web]
}
end

let(:expected_result) do
{
'name' => 'Tanaka Taro',
'age' => 30,
'address' => {
'postal_code' => '123-4567',
'city' => 'Shibuya-ku'
},
'hobbies' => [
{ 'name' => 'programming', 'level' => 3 },
{ 'level' => 2, 'years_experience' => 5 }
],
'tags' => %w[Ruby Rails Web]
}
end

it 'removes nil values recursively' do
expect(attributes).to eq(expected_result)
end
end

context 'with symbolize: true and compact: true' do
let(:symbolize) { true }
let(:compact) { true }

let(:user_param_attributes) do
{
name: 'Tanaka Taro',
email: nil,
age: 30,
address: {
postal_code: '123-4567',
prefecture: nil,
city: 'Shibuya-ku',
street: nil
},
hobbies: nil,
tags: nil
}
end

let(:expected_result) do
{
name: 'Tanaka Taro',
age: 30,
address: {
postal_code: '123-4567',
city: 'Shibuya-ku'
}
}
end

it 'symbolizes keys and removes nil values recursively' do
expect(attributes).to eq(expected_result)
end
end
end
end

describe 'edge cases' do
Expand Down