Last active
July 24, 2018 08:34
-
-
Save janko/df50fd251b591752076a to your computer and use it in GitHub Desktop.
Ruby keyword arguments advantages and use cases
This file contains hidden or 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
#### | |
# 1. Simple assertion of required arguments | |
#### | |
# - You can forget #fetch | |
# - You get a better error, and always on the line where method is defined | |
def search(options = {}) | |
query = options.fetch(:query) | |
end | |
search() # => KeyError: key not found :query | |
def search(query:) | |
# ... | |
end | |
search() # => ArgumentError: missing keyword: query | |
#### | |
# 2. Easy providing of default values | |
#### | |
# - Using #fetch can be cumbersome | |
def search(page: 1, per_page: nil, all: true) | |
# ... | |
end | |
def search(options = {}) | |
options[:page] ||= 1 | |
options[:all] ||= true # problem: gets executed when `all: false` is passed | |
end | |
def search(options = {}) | |
options[:page] = options.fetch(:page) { 1 } | |
options[:all] = options.fetch(:all) { true } | |
end | |
#### | |
# 3. Shortness | |
#### | |
def search(options = {}) | |
quizzes = Quiz.dataset | |
quizzes = quizzes.search(options[:q]) if options[:q] | |
quizzes = quizzes.where(category: options[:category]) if options[:category] | |
quizzes = quizzes.paginate(Integer(options[:page]), Integer(options[:per_page])) if options[:per_page] | |
quizzes | |
end | |
def search(q: nil, category: nil, page: 1, per_page: nil) | |
quizzes = Quiz.dataset | |
quizzes = quizzes.search(q) if q | |
quizzes = quizzes.where(category: category) if category | |
quizzes = quizzes.paginate(Integer(page), Integer(per_page)) if per_page | |
quizzes | |
end | |
#### | |
# 4. You can easily extract "special" options | |
#### | |
def make_request(params = {}) | |
raise_errors = params.fetch(:raise_errors) { true } | |
params.delete(:raise_errors) | |
response = api.request(params) | |
raise HTTPError if response.status.between?(400, 500) && raise_errors | |
response | |
end | |
def make_request(raise_errors: true, **params) | |
response = api.request(params) | |
raise HTTPError if response.status.between?(400, 500) && raise_errors | |
response | |
end | |
#### | |
# 5. Sometimes it can really help you write elegant code | |
#### | |
# - `tries` cannot be in the method body, because retry executes the whole method again, so `tries` gets reinitialized | |
def get_weather_report(tries: 3) | |
WeatherApi.get_report | |
rescue Timeout::Error | |
tries -= 1 | |
retry if tries > 0 | |
raise | |
end | |
#### | |
# 6. It's completely interchangable with Hash as options | |
#### | |
# - Everything below works | |
def search(**options) | |
options #=> Hash | |
make_request("search", options) | |
make_request("search", **options) | |
end | |
def search(options = {}) | |
options #=> Hash | |
make_request("search", options) | |
make_request("search", **options) | |
end | |
make_request(options = {}) | |
make_request(**options) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment