Skip to content

Instantly share code, notes, and snippets.

@bosunolanrewaju
Last active December 14, 2016 14:32
Show Gist options
  • Save bosunolanrewaju/eb5a79618b6795e49e224f8fd8dad0ce to your computer and use it in GitHub Desktop.
Save bosunolanrewaju/eb5a79618b6795e49e224f8fd8dad0ce to your computer and use it in GitHub Desktop.
Building nested array of hash(es) from strings separated with dots
class IncludedResourceParams
require 'facets'
attr_reader :include_param
def initialize(include_param)
@include_param = include_param
end
def has_included_resources?
included_resources.any?
end
def included_resources
return [] unless include_param
array = include_param.split(',')
array.delete_if { |str| str.include?("*") }
end
def model_includes
array = included_resources
if array.any? { |s| s.include?('.') }
b = array.map(&:split.('.'))
sup = b.dup.map { |a| recur(a.dup, {}) }
if b.size > 1 && b[0].kind_of?(Array)
sup = build_res(sup)
end
sup
else
array.map(&:to_sym)
end
end
def recur(arr, hash)
return hash if arr.empty?
if hash.empty?
last = arr.pop.to_sym
return last if arr.empty?
hash = { arr.pop.to_sym => [last] }
else
hash = { arr.pop.to_sym => [hash.dup] }
end
return recur(arr, hash)
end
def build_res(arr)
ha = {}
res = []
arr.each do |ar|
if ar.is_a? Hash
k = ar.keys.first
if ha.key? k
x = ar[k].last.is_a?(Hash) ? ar[k].dup.pop : ar[k]
y = ha[k].last.is_a?(Hash) ? ha[k].pop : ha[k]
ha[k] = [y.merge(x) { |h,i,v| i|v }].flatten
else
if ha.empty?
ha = { k => ar[k] }
else
res.unshift ar
end
end
else
res.push ar unless ha.key? ar
end
end
res.unshift ha
end
end
require 'rails_helper'
RSpec.describe IncludedResourceParams, type: :service do
# Tests for #has_included_resources?
it "test_has_included_resources_is_false_when_nil" do
r = IncludedResourceParams.new(nil)
expect(r.has_included_resources?).to eq(false)
end
it 'test_has_included_resources_is_false_when_only_wildcards' do
include_string = 'foo.**'
r = IncludedResourceParams.new(include_string)
expect(r.has_included_resources?).to eq(false)
end
it 'test_has_included_resources_is_true_with_non_wildcard_params' do
include_string = 'foo'
r = IncludedResourceParams.new(include_string)
expect(r.has_included_resources?).to eq(true)
end
it 'test_has_included_resources_is_true_with_both_wildcard_and_non_params' do
include_string = 'foo,bar.**'
r = IncludedResourceParams.new(include_string)
expect(r.has_included_resources?).to eq(true)
end
# Tests for #included_resources
it 'test_included_resources_always_returns_array' do
r = IncludedResourceParams.new(nil)
expect(r.included_resources).to eq([])
end
it 'test_included_resources_returns_only_non_wildcards' do
r = IncludedResourceParams.new('foo,foo.bar,baz.*,bat.**')
expect(r.included_resources).to eq(['foo', 'foo.bar'])
end
# Tests for #model_includes
it 'test_model_includes_when_params_nil' do
expect(IncludedResourceParams.new(nil).model_includes).to eq([])
end
it 'test_model_includes_one_single_level_resource' do
expect(IncludedResourceParams.new('foo').model_includes).to eq([:foo])
end
it 'test_model_includes_multiple_single_level_resources' do
expect(IncludedResourceParams.new('foo,bar').model_includes).to eq([:foo, :bar])
end
it 'test_model_includes_single_two_level_resource' do
expect(IncludedResourceParams.new('foo.bar').model_includes).to eq([{:foo => [:bar]}])
end
it 'test_model_includes_multiple_two_level_resources' do
expect(IncludedResourceParams.new('foo.bar,foo.bat').model_includes).to eq([{:foo => [:bar, :bat]}])
expect(IncludedResourceParams.new('foo.bar,baz.bat').model_includes).to eq([{:foo => [:bar]}, {:baz => [:bat]}])
end
it 'test_model_includes_three_level_resources' do
expect(IncludedResourceParams.new('foo.bar.baz').model_includes).to eq([{:foo => [{:bar => [:baz]}]}])
end
it 'test_model_includes_multiple_three_level_resources' do
expect(IncludedResourceParams.new('foo.bar.baz,foo,foo.bar.bat,bar').model_includes).to eq([{:foo => [{:bar => [:baz, :bat]}]}, :bar])
expect(IncludedResourceParams.new('foo.bar.baz.bat,bar').model_includes).to eq([{:foo => [{:bar => [{:baz => [:bat]}]}]}, :bar])
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment