Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exercises hash fetch #141

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
66 changes: 63 additions & 3 deletions modules/50-hash/10-hash-fetch/description.ru.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,72 @@
---

name: Hash#fetch
name: Метод fetch и извлечение значений из хеша
theory: |
В Ruby помимо стандартного способа извлечения значения из хеша существует метод fetch. В чем же принципиальное отличие?

В процессе разработки
```ruby
env = {
api_key: 123,
host: 'localhost',
port: 3000
}
puts env[:user] # -> nil
puts env.fetch(:user) # -> получим ошибку key not found (KeyError)
```

То есть если мы запрашиваем значение по несуществующему ключу через метод `[]` (не забываем в Ruby - все есть объект и соответственно `[]` обычный метод объекта Hash), он молча возвращает `nil`.
Метод `fetch` же действует иначе - если ключа не существует, мы получим ошибку КеуError

Метод `fetch` принимает вторым параметром значение по умалчанию:

```ruby
env = {
api_key: 123,
host: 'localhost',
port: 3000
}
puts env.fetch(:user, nil) # -> nil
puts env.fetch(:user, 'guest') # -> 'guest'
```

И даже блок или `lambda`:

```ruby
env = { host: 'localhost' }

env.fetch(:user) { |key| env[key] = 'guest' }
puts env # -> { host: 'localhost', user: 'guest' }

```

А вот конфигурация почтовой рассылки из приложения на Ruby on Rails:

```ruby
config.action_mailer.smtp_settings = {
user_name: ENV.fetch('MAIL_USERNAME', nil),
password: ENV.fetch('MAIL_PASSWORD', nil),
address: ENV.fetch('MAIL_HOST', nil),
domain: ENV.fetch('MAIL_HOST', nil),
port: ENV.fetch('SMTP_PORT', '25'),
authentication: :cram_md5
}
```
Кстати если следовать ruby style guide метод `fetch` является более приоритетным.

**[fetch()](https://apidock.com/ruby/Hash/fetch)**

instructions: |
Реализуйте функцию `setup_env()`, которая принимает: ключ, параметры в виде hash и блок который в свою очередь тоже принимает два параметра - это ключ и hash из параметров функции.
Если переданного ключа нет в передаваемом hash, то тогда нужно вызвать блок, передав в него первым аргументом ключ, а вторым hash, если есть - вернуть исходный hash:

```ruby
env = { api_key: 123 }
setup_env(:host, env) { |env, key| env[key] = 'localhost' } # -> { api_key: 123, host: 'lockalhost' }
setup_env(:api_key, env) { |env, key| env[key] = 'localhost' } # -> { api_key: 123 }
env == { api_key: 123 } # -> true
```

Функция не должна мутировать исходный объект.

В процессе разработки

tips: []
5 changes: 5 additions & 0 deletions modules/50-hash/10-hash-fetch/index.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# frozen_string_literal: true

# BEGIN
def setup_env(key, hash)
new_config = {}.merge(hash)
new_config.fetch(key) { yield(new_config, key) }
new_config
end
# END
18 changes: 14 additions & 4 deletions modules/50-hash/10-hash-fetch/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@
require 'test_helper'
require_relative './index'

# describe 'function' do
# it 'should works' do
# end
# end
describe 'test setup_env' do
it 'should works' do
env = { api_key: 123 }
no_key = setup_env(
:host,
env
) { |config, key| config[key] = 'localhost' }

expected = { api_key: 123, host: 'localhost' }

assert { no_key == expected }
assert { env == { api_key: 123 } }
end
end