Last active
October 15, 2019 10:29
-
-
Save DonSchado/171b1e758bd6c649e36c5948cebb21df to your computer and use it in GitHub Desktop.
Railslove Ruby programming exercise A4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Railslove Ruby programming exercise A4 | |
# | |
# To run the following exercise you need to have rspec installed. | |
# Then inspect the failing specs by running `rspec translations.rb` | |
# | |
# This excercise is special, because it's the first one where you're allowed to require active_support. ;-) | |
# | |
# (!) The task is to navigate and write into a nested hash via a path represented as `.` separated keys. | |
# | |
# (?) Maybe start with the underling algorithm to expand a collection to a "directed graph" | |
# and then implement the rest of the `#set` method to make the tests pass. | |
# | |
# Refactor until you're happy with your solution, by asking the follwing questions: | |
# * Is the code understandable/maintainable? | |
# * Do I really need all these if/else/elsif statements? | |
# | |
require 'active_support' | |
class TranslationsHash | |
attr_reader :translations | |
def initialize(translations = {}) | |
@translations = translations | |
end | |
def set(path, value) | |
# TODO: this should call somehow the private method | |
end | |
private | |
def expand_to_directed_hash(collection) | |
# your code goes here | |
end | |
end | |
# # don't touch me | |
require 'rspec' | |
RSpec.describe 'TranslationsHash' do | |
let(:data) do | |
{ foo: { bar: 'value' } } | |
end | |
subject(:translations) { TranslationsHash.new(data) } | |
describe '#expand_to_directed_hash' do | |
let(:expansion) { subject.method(:expand_to_directed_hash) } | |
it { expect(expansion.call([:a, 'v'])).to eq({ a: 'v' }) } | |
it { expect(expansion.call([:a, :b, 'v'])).to eq({ a: { b: 'v' } }) } | |
it { expect(expansion.call([:a, :b, :c, 'v'])).to eq({ a: { b: { c: 'v' } } }) } | |
it { expect(expansion.call([:a, :b, :c, :d, 'v'])).to eq({ a: { b: { c: { d: 'v' } } } }) } | |
it { expect(expansion.call([:a, :b, :c, :d, { e: 'f' }])).to eq({ a: { b: { c: { d: { e: 'f' } } } } }) } | |
end | |
describe '#set' do | |
it 'overwrites values when last in the chain' do | |
expect(subject.set('foo', nil)).to match({ foo: nil }) | |
expect(subject.set('foo', 'bar')).to match({ foo: 'bar' }) | |
expect(subject.set('foo', [])).to match({ foo: [] }) | |
end | |
it 'does not merge empty hash (due to #deep_merge, if required use #merge for this case)' do | |
expect(subject.set('foo', {})).to match(data) | |
end | |
it 'navigates dots to deep merge values' do | |
expect(subject.set('foo.baz', 'yay')).to match({ foo: { bar: 'value' , baz: 'yay' } }) | |
expect(subject.set('foo.baz.we.need.to.go', 'deeper')). | |
to match(hash_including({ foo: { bar: 'value', baz: { we: { need: { to: { go: 'deeper' } } } } } })) | |
end | |
context 'nested value merge' do | |
let(:data) do | |
{ foo: { bar: { countries: { fr: 'FR' } } } } | |
end | |
it 'deep merges current data via key or value' do | |
expect(subject.set('foo.bar', { countries: { de: 'DE' } })). | |
to match({ foo: { bar: { countries: { fr: 'FR', de: 'DE' } } } } ) | |
expect(subject.set('foo', { bar: { countries: { de: 'DE' } } })). | |
to match({ foo: { bar: { countries: { fr: 'FR', de: 'DE' } } } } ) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment