Skip to content

Instantly share code, notes, and snippets.

@dsalahutdinov
Last active August 29, 2015 14:02
Show Gist options
  • Save dsalahutdinov/76dc70ec8ef06f51eaa4 to your computer and use it in GitHub Desktop.
Save dsalahutdinov/76dc70ec8ef06f51eaa4 to your computer and use it in GitHub Desktop.
# Представим, что у нас есть некоторый внешний источник, который возвращает нам данные в виде массива хэшей.
# Причём все значения в хэшах передаются как строки. Создайте такой универсальный класс Storage, который позволит
# создавать классы преобразователи:
require 'time'
class Storage
def self.attrb(attribute_name, attribute_accessor = nil, &process_proc)
raise ArgumentError if attribute_name.nil?
unless process_proc.nil?
define_method("process_#{attribute_name}") do |value|
process_proc.call(value)
end
return
end
unless attribute_accessor.nil?
define_method("process_#{attribute_name}") do |value|
value.send(attribute_accessor)
end
return
end
define_method("process_#{attribute_name}") do |value|
value
end
end
include Enumerable
def each
@data.each {|d| yield d }
end
def initialize(data)
@data = data.collect do |data_item|
data_item.keys.inject({}) {|hash, key| hash[key] = send("process_#{key}", data_item[key]); hash }
end
end
end
class Transactions < Storage
attrb :uid # значение будет передаваться как есть
attrb :sum, :to_f # для преобразования значения будет вызван его(значения) метод to_f '50.25'.to_f
# для преобразования значение будет вызван блок, который принимает исходное значение и возвращает преобразованное
attrb :timestamp do |value|
Time.parse(value)
end
def sum
@data.collect{|h| h[:sum] }.inject(0) {|s, v| s += v }
end
end
transactions = Transactions.new([
# входной массив хэшей где все значения - строки
{:uid => 'HT150', :sum => '50.25', :timestamp => '2014-04-04 05:50'},
{:uid => 'HT151', :sum => '119.63', :timestamp => '2014-04-04 06:18'}
])
# а здесь значения преобразованы согласно правилам преобразованиия, описанным в Transactions
transactions.to_a
# => [{:uid=>"HT150", :sum=>50.25, :timestamp=>2014-04-04 05:50:00 +0600}, {:uid=>"HT151", :sum=>119.63, :timestamp=>2014-04-04 06:18:00 +0600}]
transactions.first # => {:uid=>"HT150", :sum=>50.25, :timestamp=>2014-04-04 05:50:00 +0600}
transactions.select { |tx| tx[:sum] > 100 } # => [{:uid => 'HT151', :sum => 119.63, :timestamp => 2014-04-04 06:18:00 +0600}]
transactions.sum # => 169.88
# для проверки вашего класса Storage я могу создать любой другой класс:
class People < Storage
attrb :name
attrb :height, :to_i
attrb :birthday do |value|
Date.parse(value)
end
end
ppl = People.new([{:name => 'Vlas', :height => '205', :birthday => '1990-08-08'}])
ppl.first # => {:name => 'Vlas', :height => 205, :birthday => Wed, 08 Aug 1990}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment