Skip to content

Commit 19bab58

Browse files
authored
Allow underscore navigation (#193)
* Allow underscore navigation * rubocop
1 parent cf8abb0 commit 19bab58

5 files changed

Lines changed: 68 additions & 9 deletions

File tree

.rubocop.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Layout/SpaceInsideHashLiteralBraces:
1010
Lint/AssignmentInCondition:
1111
Enabled: false
1212

13+
Metrics/CyclomaticComplexity:
14+
Max: 9
15+
Metrics/PerceivedComplexity:
16+
Max: 9
17+
1318
Style/ClassAndModuleChildren:
1419
Enabled: false
1520
Style/ConditionalAssignment:

lib/ja2r/element.rb

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ class Element
33
def initialize(origin_data, options = {})
44
@origin_data = origin_data.with_indifferent_access
55
@options = options
6-
@relationships = origin_data['relationships'] ? convert_relationships(origin_data['relationships']) : {}
6+
@relationships = origin_data['relationships']&.then { |rd| convert_relationships(rd) } || {}
7+
build_references
78
end
89

910
attr_reader :origin_data, :relationships
@@ -39,18 +40,31 @@ def type
3940

4041
private
4142

42-
def method_missing(symbol, *args)
43-
return attributes[symbol] if attributes&.key? symbol
44-
return relationships[symbol] if relationships&.key? symbol
43+
def build_references
44+
@references = {}.with_indifferent_access
45+
attributes&.each_key do |key|
46+
@references[key] ||= {attribute: key}
47+
@references[key.underscore] ||= {attribute: key}
48+
end
49+
relationships&.each_key do |key|
50+
@references[key] ||= {relationship: key}
51+
@references[key.underscore] ||= {relationship: key}
52+
end
53+
end
4554

46-
safe_traverse? ? nil : super
55+
def method_missing(symbol, *args)
56+
case @references[symbol]
57+
in attribute:
58+
attributes[attribute]
59+
in relationship:
60+
relationships[relationship]
61+
else
62+
safe_traverse? ? nil : super
63+
end
4764
end
4865

4966
def respond_to_missing?(symbol, include_all = false)
50-
return true if attributes&.key?(symbol)
51-
return true if relationships&.key?(symbol)
52-
53-
safe_traverse? || super
67+
@references.key?(symbol) || safe_traverse? || super
5468
end
5569

5670
def safe_traverse?

spec/fixtures/singular.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
"example": true
1313
},
1414
"relationships":{
15+
"best-friend":{
16+
"data":{
17+
"id":"1005",
18+
"type":"persons"
19+
}
20+
},
1521
"sister":{
1622
"data":{
1723
"id":"1002",
@@ -34,6 +40,13 @@
3440
"name":"Lisa"
3541
}
3642
},
43+
{
44+
"id":"1005",
45+
"type":"persons",
46+
"attributes":{
47+
"name":"Milhouse"
48+
}
49+
},
3750
{
3851
"id":"998",
3952
"type":"persons",

spec/ja2r/element_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,30 @@
4343
end
4444
end
4545
end
46+
47+
context 'with dashes in the keys' do
48+
let(:origin_data) do
49+
{
50+
'id' => 'some-id',
51+
'attributes' => {
52+
'foo-field' => 'foo-value',
53+
'bar-field' => {
54+
'bar-value' => true
55+
}
56+
},
57+
'relationships' => {
58+
'some-one' => {
59+
'data' => {'id' => '1122', 'type' => 'some-ones'}
60+
}
61+
}
62+
}
63+
end
64+
65+
it 'allows navigation with underscore' do
66+
expect(element.foo_field).to eq 'foo-value'
67+
expect(element.bar_field).to eq('bar-value' => true)
68+
expect(element.some_one).to be_a(described_class)
69+
expect(element.some_one.type).to eq('some-ones')
70+
end
71+
end
4672
end

spec/ja2r_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
it 'can handle singular relations' do
66
ele = described_class.parse payload
77
expect(ele.id).to eq '1001'
8+
expect(ele.best_friend.name).to eq 'Milhouse'
89
expect(ele.sister.id).to eq '1002'
910
expect(ele.sister.name).to eq 'Lisa'
1011
expect(ele.father.id).to eq '998'

0 commit comments

Comments
 (0)