Skip to content

Instantly share code, notes, and snippets.

@kana-sama
Last active August 29, 2015 14:23
Show Gist options
  • Save kana-sama/615a05d68fa8fa142267 to your computer and use it in GitHub Desktop.
Save kana-sama/615a05d68fa8fa142267 to your computer and use it in GitHub Desktop.
# Я только-только начал изучать Ruby, мне очень понравилось то, что
# в языке очень много сахара. Но при этом там нет сахара для быстрых
# конструкторов, которые есть даже в C++ и CS
# constructor: (@name, @age) ->
class PersonOld
def initialize(name, age)
# вот эти строки меня и бесят
@name = name
@age = age
end
def to_s
"My name is #{@name} and I am #{@age} years old."
end
end
# Поэтому я решил написать метод (я так понял, это называется объявление),
# который создает такие конструкторы
class Class
private
class ArgumentPair < Array
def name
"ArgumentPair"
end
end
def initializer_for(*attrs, **attrs_hash, &after_initialize)
define_method :initialize do |*values|
unless attrs_hash.nil?
attrs += attrs_hash.to_a.map { |a| ArgumentPair.new(a) }
end
Array(attrs).zip(Array(values)).each.with_index do |(a, v), i|
attr, val = a, v
if a.is_a? ArgumentPair
attr = attrs[i][0]
val = attrs[i][1] if val.nil?
end
instance_variable_set("@#{attr.to_s}", val.to_s)
end
instance_eval(&after_initialize) if block_given?
end
end
end
# Теперь можно писать так
class PersonExample
initializer_for :name, "age"
def to_s
"My name is #{@name} and I am #{@age} years old."
end
end
# Добавил несколько фич: значения по умолчанию и код, который выполнится
# в конце конструктора
class Person
initializer_for :name, age: 17 do
@name.capitalize!
end
def to_s
"My name is #{@name} and I am #{@age} years old."
end
end
# В итоге имеем
me = Person.new("andrew")
puts me
# => Hello, my name is Andrew and I am 17 years old!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment