Решение на Пета задача - DataModel от Добрин Цветков

Обратно към всички решения

Към профила на Добрин Цветков

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 24 успешни тест(а)
  • 1 неуспешни тест(а)

Код

module SubHashChecker
def sub_hash?(main_hash, sub_hash)
main_hash.merge(sub_hash) == main_hash
end
end
module DataModelSingletonMethods
def data_store(repository = nil)
if repository
@repository = repository
else
@repository
end
end
def attributes(*attribute_names)
if attribute_names.empty?
@attribute_names
else
@attribute_names = attribute_names
@attribute_names << :id
end
@attribute_names.each { |attribute| attr_accessor attribute }
end
def where(criteria)
check_for_invalid_keys(criteria, @attribute_names)
result = []
@repository.storage.each do |current_hash|
current_hash = current_hash[1] if current_hash.is_a? Array
add_to_result(result, current_hash) if sub_hash?(current_hash, criteria)
end
result
end
def add_to_result(result, current_hash_informations)
new_instance = self.new(current_hash_informations)
new_instance.saved_to_repository = true
result << new_instance
end
end
module InitializeHelpers
def initialize_attributes(names, information_hash)
names.each do |attribute|
value = information_hash[attribute]
if value
send("#{attribute}=".to_sym, value)
else
send("#{attribute}=".to_sym, nil)
end
end
end
def initialize_singleton_finders(names, which_class)
names.each do |attribute|
which_class.define_singleton_method "find_by_#{attribute}".to_sym do |value|
hash_attribute = {attribute => value}
which_class.where(hash_attribute)
end
end
end
end
module Helpers
include SubHashChecker
include InitializeHelpers
def check_for_invalid_keys(criteria_hash, attribute_names)
criteria_hash.each do |key, _|
unless attribute_names.include?(key)
raise DataModel::UnknownAttributeError, "Unknown attribute #{key}"
end
end
end
def find_id_for_instance(instance, repository)
repository.max_used_id += 1
@id = repository.max_used_id
instance[:id] = @id
repository.create(instance)
@saved_to_repository = true
end
end
class HashStore
include Helpers
attr_reader :storage
attr_accessor :max_used_id
def initialize
@storage = {}
@max_used_id = 0
end
def create(information_hash)
id = information_hash[:id]
@storage[id] = information_hash
end
def find(search_hash)
result = []
@storage.each do |_, current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
id = current_hash[:id]
@storage.delete(id)
end
end
end
class ArrayStore
include Helpers
attr_reader :storage
attr_accessor :max_used_id
def initialize
@storage = []
@max_used_id = 0
end
def create(information_hash)
@storage << information_hash
end
def find(search_hash)
result = []
@storage.each do |current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
storage.each do |current_hash|
if current_hash[:id] == id
desired_hash = current_hash
break
end
end
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
@storage.delete(current_hash)
end
end
end
class DataModel
include Helpers
extend Helpers
extend DataModelSingletonMethods
class DeleteUnsavedRecordError < RuntimeError; end
class UnknownAttributeError < RuntimeError; end
attr_accessor :saved_to_repository
def initialize(information_hash = {})
names = self.class.instance_variable_get(:@attribute_names)
initialize_attributes(names, information_hash)
@saved_to_repository = false
initialize_singleton_finders(names, self.class)
end
def hash_information
names = self.class.instance_variable_get(:@attribute_names)
result = {}
names.each do |attribute|
result[attribute] = send attribute
end
result.delete(:id)
result
end
def save
repository = self.class.instance_variable_get(:@repository)
instance = hash_information
if !@saved_to_repository
find_id_for_instance(instance, repository)
else
repository.update(repository.find({id: @id})[0][:id], instance)
end
self
end
def delete
repository = self.class.instance_variable_get(:@repository)
if repository.find(hash_information) == []
raise DeleteUnsavedRecordError
else
repository.delete(hash_information)
@saved_to_repository = false
end
end
def ==(other)
return false unless other.instance_of?(self.class)
if @saved_to_repository && other.saved_to_repository && id == other.id
true
else
self.equal?(other)
end
end
end

Лог от изпълнението

............F............

Failures:

  1) DataModel.where raises an error if the query is by an unknown key
     Failure/Error: expect { user_model.where(middle_name: 'Ivanov') }.to raise_error(
       expected DataModel::UnknownAttributeError with "Unknown attribute middle_name", got #<DataModel::UnknownAttributeError: Unknown attribute  middle_name> with backtrace:
         # /tmp/d20161202-15620-nvj0ke/solution.rb:68:in `block in check_for_invalid_keys'
         # /tmp/d20161202-15620-nvj0ke/solution.rb:66:in `each'
         # /tmp/d20161202-15620-nvj0ke/solution.rb:66:in `check_for_invalid_keys'
         # /tmp/d20161202-15620-nvj0ke/solution.rb:26:in `where'
         # /tmp/d20161202-15620-nvj0ke/spec.rb:143:in `block (4 levels) in <top (required)>'
         # /tmp/d20161202-15620-nvj0ke/spec.rb:143:in `block (3 levels) in <top (required)>'
         # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
         # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'
     # /tmp/d20161202-15620-nvj0ke/spec.rb:143:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

Finished in 0.02614 seconds
25 examples, 1 failure

Failed examples:

rspec /tmp/d20161202-15620-nvj0ke/spec.rb:142 # DataModel.where raises an error if the query is by an unknown key

История (7 версии и 7 коментара)

Добрин обнови решението на 25.11.2016 18:50 (преди над 7 години)

+module SubHashChecker
+ def sub_hash?(main_hash, sub_hash)
+ sub_hash.each do |key, value|
+ return false if main_hash[key] != value
+ end
+ true
+ end
+end
+
+module DataModelSingletonMethods
+ def data_store(repository = nil)
+ if repository
+ instance_variable_set(:@repository, repository)
+ else
+ instance_variable_get(:@repository)
+ end
+ end
+
+ def attributes(*attribute_names)
+ if attribute_names.empty?
+ instance_variable_get(:@attribute_names)
+ else
+ instance_variable_set(:@attribute_names, attribute_names)
+ @attribute_names << :id
+ end
+ @attribute_names.each { |attribute| attr_accessor attribute }
+ end
+
+ def where(criteria)
+ check_for_invalid_keys(criteria, @attribute_names)
+ result = []
+ ObjectSpace.each_object(self) do |x|

Но в data store-a имам само хешове, а не конкретни инстанции на модел. Нали where трябва да връща инстанции?! Тогава да обходя data store и за всеки хеш, който изпълнява критерийте да създам нова инстанция ли?

Да. DataStore-а ти е като файл. Във файл няма как да имаш инстанция на клас - имаш някаква структурирана информация (например, json).

В условието пише Задача на самия модел е да преобразува инстанции от и към хешове преди да ги подаде на/вземе от съответния store.

+ predicate1 = x.instance_variable_get(:@saved_to_repository)
+ predicate2 = sub_hash?(x.hash_information, criteria)
+ result << x if predicate1 && predicate2
+ end
+ result
+ end
+end
+
+module InitializeHelpers
+ def initialize_attributes(names, information_hash)
+ names.each do |attribute|
+ value = information_hash[attribute]
+ if value
+ send("#{attribute}=".to_sym, value)
+ else
+ send("#{attribute}=".to_sym, nil)
+ end
+ end
+ end
+
+ def initialize_singleton_finders(names, which_class)
+ names.each do |attribute|
+ which_class.define_singleton_method "find_by_#{attribute}".to_sym do |value|
+ hash_attribute = {attribute => value}
+ which_class.where(hash_attribute)
+ end
+ end
+ end
+end
+
+module Helpers
+ include SubHashChecker
+ include InitializeHelpers
+
+ def check_for_invalid_keys(criteria_hash, attribute_names)
+ criteria_hash.each do |key, _|
+ unless attribute_names.include?(key)
+ raise DataModel::UnknownAttributeError, "Unknown attribute #{key}"
+ end
+ end
+ end
+
+ def find_id_for_instance(instance, repository)
+ @id = 1
+ @id += 1 while repository.find({id: @id}) != []
+ instance[:id] = @id
+ repository.create(instance)
+ @saved_to_repository = true
+ end
+end
+
+class HashStore
+ include Helpers
+ attr_reader :storage
+ def initialize
+ @storage = {}
+ end
+
+ def create(information_hash)
+ id = information_hash[:id]
+ @storage[id] = information_hash
+ end
+
+ def find(search_hash)
+ result = []
+ @storage.each do |_, current_hash|
+ result << current_hash if sub_hash?(current_hash, search_hash)
+ end
+ result
+ end
+
+ def update(id, to_overload)
+ desired_hash = storage[id]
+ to_overload.each do |key, value|
+ desired_hash[key] = value
+ end
+ end
+
+ def delete(search_hash)
+ matches = find(search_hash)
+ matches.each do |current_hash|
+ id = current_hash[:id]
+ @storage.delete(id)
+ end
+ end
+end
+
+class ArrayStore
+ include Helpers
+ attr_reader :storage
+ def initialize
+ @storage = []
+ end
+
+ def create(information_hash)
+ @storage << information_hash
+ end
+
+ def find(search_hash)
+ result = []
+ @storage.each do |current_hash|
+ result << current_hash if sub_hash?(current_hash, search_hash)
+ end
+ result
+ end
+
+ def update(id, to_overload)
+ desired_hash = storage[id]
+ storage.each do |current_hash|
+ if current_hash[:id] == id
+ desired_hash = current_hash
+ break
+ end
+ end
+ to_overload.each do |key, value|
+ desired_hash[key] = value
+ end
+ end
+
+ def delete(search_hash)
+ matches = find(search_hash)
+ matches.each do |current_hash|
+ @storage.delete(current_hash)
+ end
+ end
+end
+
+class DataModel
+ include Helpers
+ extend Helpers
+ extend DataModelSingletonMethods
+ class DeleteUnsavedRecordError < RuntimeError; end
+ class UnknownAttributeError < RuntimeError; end
+ attr_reader :saved_to_repository
+
+ def initialize(information_hash = {})
+ names = self.class.instance_variable_get(:@attribute_names)
+ initialize_attributes(names, information_hash)
+ @id = 1
+ @saved_to_repository = false
+ initialize_singleton_finders(names, self.class)
+ end
+
+ def hash_information
+ names = self.class.instance_variable_get(:@attribute_names)
+ result = {}
+ names.each do |attribute|
+ result[attribute] = send attribute
+ end
+ result.delete(:id)
+ result
+ end
+
+ def save
+ repository = self.class.instance_variable_get(:@repository)
+ instance = hash_information
+ if !@saved_to_repository
+ find_id_for_instance(instance, repository)
+ else
+ repository.update(repository.find(instance)[0][:id], instance)
+ end
+ self
+ end
+
+ def delete
+ repository = self.class.instance_variable_get(:@repository)
+ if repository.find(hash_information) == []
+ raise DeleteUnsavedRecordError
+ else
+ repository.delete(hash_information)
+ end
+ end
+
+ def ==(other)
+ return false unless other.instance_of?(self.class)
+ if @saved_to_repository && other.saved_to_repository && id == other.id
+ true
+ else
+ self.equal?(other)
+ end
+ end
+end

Направил си го милион пъти по-сложно, отколкото трябва. Като страничен ефект, няма да работи правилно.

Изчети пак лекциите за модулите и не наблягай толкова на метапрограмирането.

Добрин обнови решението на 25.11.2016 22:06 (преди над 7 години)

module SubHashChecker
def sub_hash?(main_hash, sub_hash)
- sub_hash.each do |key, value|
- return false if main_hash[key] != value
- end
- true
+ # sub_hash.each do |key, value|
+ # return false if main_hash[key] != value
+ # end
+ # true
+ main_hash.merge(sub_hash) == main_hash
end
end
module DataModelSingletonMethods
def data_store(repository = nil)
if repository
- instance_variable_set(:@repository, repository)
+ @repository = repository
else
- instance_variable_get(:@repository)
+ @repository
end
end
def attributes(*attribute_names)
if attribute_names.empty?
- instance_variable_get(:@attribute_names)
+ @attribute_names
else
- instance_variable_set(:@attribute_names, attribute_names)
+ @attribute_names = attribute_names
@attribute_names << :id
end
@attribute_names.each { |attribute| attr_accessor attribute }
end
def where(criteria)
check_for_invalid_keys(criteria, @attribute_names)
result = []
- ObjectSpace.each_object(self) do |x|
- predicate1 = x.instance_variable_get(:@saved_to_repository)
- predicate2 = sub_hash?(x.hash_information, criteria)
- result << x if predicate1 && predicate2
+ # ObjectSpace.each_object(self) do |x|
+ # predicate1 = x.instance_variable_get(:@saved_to_repository)
+ # predicate2 = sub_hash?(x.hash_information, criteria)
+ # result << x if predicate1 && predicate2
+ # end
+ @repository.storage.each do |current_hash|
+ result << self.new(current_hash) if sub_hash?(current_hash, criteria)
end
result
end
end
module InitializeHelpers
def initialize_attributes(names, information_hash)
names.each do |attribute|
value = information_hash[attribute]
if value
send("#{attribute}=".to_sym, value)
else
send("#{attribute}=".to_sym, nil)
end
end
end
def initialize_singleton_finders(names, which_class)
names.each do |attribute|
which_class.define_singleton_method "find_by_#{attribute}".to_sym do |value|
hash_attribute = {attribute => value}
which_class.where(hash_attribute)
end
end
end
end
module Helpers
include SubHashChecker
include InitializeHelpers
def check_for_invalid_keys(criteria_hash, attribute_names)
criteria_hash.each do |key, _|
unless attribute_names.include?(key)
raise DataModel::UnknownAttributeError, "Unknown attribute #{key}"
end
end
end
def find_id_for_instance(instance, repository)
@id = 1
@id += 1 while repository.find({id: @id}) != []
instance[:id] = @id
repository.create(instance)
@saved_to_repository = true
end
end
class HashStore
include Helpers
attr_reader :storage
def initialize
@storage = {}
end
def create(information_hash)
id = information_hash[:id]
@storage[id] = information_hash
end
def find(search_hash)
result = []
@storage.each do |_, current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
id = current_hash[:id]
@storage.delete(id)
end
end
end
class ArrayStore
include Helpers
attr_reader :storage
def initialize
@storage = []
end
def create(information_hash)
@storage << information_hash
end
def find(search_hash)
result = []
@storage.each do |current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
storage.each do |current_hash|
if current_hash[:id] == id
desired_hash = current_hash
break
end
end
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
@storage.delete(current_hash)
end
end
end
class DataModel
include Helpers
extend Helpers
extend DataModelSingletonMethods
class DeleteUnsavedRecordError < RuntimeError; end
class UnknownAttributeError < RuntimeError; end
attr_reader :saved_to_repository
def initialize(information_hash = {})
names = self.class.instance_variable_get(:@attribute_names)
initialize_attributes(names, information_hash)
@id = 1
@saved_to_repository = false
initialize_singleton_finders(names, self.class)
end
def hash_information
names = self.class.instance_variable_get(:@attribute_names)
result = {}
names.each do |attribute|
result[attribute] = send attribute
end
result.delete(:id)
result
end
def save
repository = self.class.instance_variable_get(:@repository)
instance = hash_information
if !@saved_to_repository
find_id_for_instance(instance, repository)
else
repository.update(repository.find(instance)[0][:id], instance)
end
self
end
def delete
repository = self.class.instance_variable_get(:@repository)
if repository.find(hash_information) == []
raise DeleteUnsavedRecordError
else
repository.delete(hash_information)
end
end
def ==(other)
return false unless other.instance_of?(self.class)
if @saved_to_repository && other.saved_to_repository && id == other.id
true
else
self.equal?(other)
end
end
end

Добрин обнови решението на 25.11.2016 22:06 (преди над 7 години)

module SubHashChecker
def sub_hash?(main_hash, sub_hash)
# sub_hash.each do |key, value|
# return false if main_hash[key] != value
# end
# true
main_hash.merge(sub_hash) == main_hash
end
end
module DataModelSingletonMethods
def data_store(repository = nil)
if repository
@repository = repository
else
@repository
end
end
def attributes(*attribute_names)
if attribute_names.empty?
@attribute_names
else
@attribute_names = attribute_names
@attribute_names << :id
end
@attribute_names.each { |attribute| attr_accessor attribute }
end
def where(criteria)
check_for_invalid_keys(criteria, @attribute_names)
result = []
- # ObjectSpace.each_object(self) do |x|
- # predicate1 = x.instance_variable_get(:@saved_to_repository)
- # predicate2 = sub_hash?(x.hash_information, criteria)
- # result << x if predicate1 && predicate2
- # end
@repository.storage.each do |current_hash|
result << self.new(current_hash) if sub_hash?(current_hash, criteria)
end
result
end
end
module InitializeHelpers
def initialize_attributes(names, information_hash)
names.each do |attribute|
value = information_hash[attribute]
if value
send("#{attribute}=".to_sym, value)
else
send("#{attribute}=".to_sym, nil)
end
end
end
def initialize_singleton_finders(names, which_class)
names.each do |attribute|
which_class.define_singleton_method "find_by_#{attribute}".to_sym do |value|
hash_attribute = {attribute => value}
which_class.where(hash_attribute)
end
end
end
end
module Helpers
include SubHashChecker
include InitializeHelpers
def check_for_invalid_keys(criteria_hash, attribute_names)
criteria_hash.each do |key, _|
unless attribute_names.include?(key)
raise DataModel::UnknownAttributeError, "Unknown attribute #{key}"
end
end
end
def find_id_for_instance(instance, repository)
@id = 1
@id += 1 while repository.find({id: @id}) != []
instance[:id] = @id
repository.create(instance)
@saved_to_repository = true
end
end
class HashStore
include Helpers
attr_reader :storage
def initialize
@storage = {}
end
def create(information_hash)
id = information_hash[:id]
@storage[id] = information_hash
end
def find(search_hash)
result = []
@storage.each do |_, current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
id = current_hash[:id]
@storage.delete(id)
end
end
end
class ArrayStore
include Helpers
attr_reader :storage
def initialize
@storage = []
end
def create(information_hash)
@storage << information_hash
end
def find(search_hash)
result = []
@storage.each do |current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
storage.each do |current_hash|
if current_hash[:id] == id
desired_hash = current_hash
break
end
end
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
@storage.delete(current_hash)
end
end
end
class DataModel
include Helpers
extend Helpers
extend DataModelSingletonMethods
class DeleteUnsavedRecordError < RuntimeError; end
class UnknownAttributeError < RuntimeError; end
attr_reader :saved_to_repository
def initialize(information_hash = {})
names = self.class.instance_variable_get(:@attribute_names)
initialize_attributes(names, information_hash)
@id = 1
@saved_to_repository = false
initialize_singleton_finders(names, self.class)
end
def hash_information
names = self.class.instance_variable_get(:@attribute_names)
result = {}
names.each do |attribute|
result[attribute] = send attribute
end
result.delete(:id)
result
end
def save
repository = self.class.instance_variable_get(:@repository)
instance = hash_information
if !@saved_to_repository
find_id_for_instance(instance, repository)
else
repository.update(repository.find(instance)[0][:id], instance)
end
self
end
def delete
repository = self.class.instance_variable_get(:@repository)
if repository.find(hash_information) == []
raise DeleteUnsavedRecordError
else
repository.delete(hash_information)
end
end
def ==(other)
return false unless other.instance_of?(self.class)
if @saved_to_repository && other.saved_to_repository && id == other.id
true
else
self.equal?(other)
end
end
end

Добрин обнови решението на 26.11.2016 17:51 (преди над 7 години)

module SubHashChecker
def sub_hash?(main_hash, sub_hash)
- # sub_hash.each do |key, value|
- # return false if main_hash[key] != value
- # end
- # true
main_hash.merge(sub_hash) == main_hash
end
end
module DataModelSingletonMethods
def data_store(repository = nil)
if repository
@repository = repository
else
@repository
end
end
def attributes(*attribute_names)
if attribute_names.empty?
@attribute_names
else
@attribute_names = attribute_names
@attribute_names << :id
end
@attribute_names.each { |attribute| attr_accessor attribute }
end
def where(criteria)
check_for_invalid_keys(criteria, @attribute_names)
result = []
@repository.storage.each do |current_hash|
result << self.new(current_hash) if sub_hash?(current_hash, criteria)
end
result
end
end
module InitializeHelpers
def initialize_attributes(names, information_hash)
names.each do |attribute|
value = information_hash[attribute]
if value
send("#{attribute}=".to_sym, value)
else
send("#{attribute}=".to_sym, nil)
end
end
end
def initialize_singleton_finders(names, which_class)
names.each do |attribute|
which_class.define_singleton_method "find_by_#{attribute}".to_sym do |value|
hash_attribute = {attribute => value}
which_class.where(hash_attribute)
end
end
end
end
module Helpers
include SubHashChecker
include InitializeHelpers
def check_for_invalid_keys(criteria_hash, attribute_names)
criteria_hash.each do |key, _|
unless attribute_names.include?(key)
raise DataModel::UnknownAttributeError, "Unknown attribute #{key}"
end
end
end
def find_id_for_instance(instance, repository)
@id = 1
@id += 1 while repository.find({id: @id}) != []
instance[:id] = @id
repository.create(instance)
@saved_to_repository = true
end
end
class HashStore
include Helpers
attr_reader :storage
def initialize
@storage = {}
end
def create(information_hash)
id = information_hash[:id]
@storage[id] = information_hash
end
def find(search_hash)
result = []
@storage.each do |_, current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
id = current_hash[:id]
@storage.delete(id)
end
end
end
class ArrayStore
include Helpers
attr_reader :storage
def initialize
@storage = []
end
def create(information_hash)
@storage << information_hash
end
def find(search_hash)
result = []
@storage.each do |current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
storage.each do |current_hash|
if current_hash[:id] == id
desired_hash = current_hash
break
end
end
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
@storage.delete(current_hash)
end
end
end
class DataModel
include Helpers
extend Helpers
extend DataModelSingletonMethods
class DeleteUnsavedRecordError < RuntimeError; end
class UnknownAttributeError < RuntimeError; end
attr_reader :saved_to_repository
def initialize(information_hash = {})
names = self.class.instance_variable_get(:@attribute_names)
initialize_attributes(names, information_hash)
@id = 1
@saved_to_repository = false
initialize_singleton_finders(names, self.class)
end
def hash_information
names = self.class.instance_variable_get(:@attribute_names)
result = {}
names.each do |attribute|
result[attribute] = send attribute
end
result.delete(:id)
result
end
def save
repository = self.class.instance_variable_get(:@repository)
instance = hash_information
if !@saved_to_repository
find_id_for_instance(instance, repository)
else
repository.update(repository.find(instance)[0][:id], instance)
end
self
end
def delete
repository = self.class.instance_variable_get(:@repository)
if repository.find(hash_information) == []
raise DeleteUnsavedRecordError
else
repository.delete(hash_information)
end
end
def ==(other)
return false unless other.instance_of?(self.class)
if @saved_to_repository && other.saved_to_repository && id == other.id
true
else
self.equal?(other)
end
end
end

Кодът: https://gist.github.com/DobrinTs/6e707e6639d4efb986bbf36b9c36cd57 . В моята програма като го напиша не ъпдейтва вече съществуващия User, защото търси по новото име, а вместо това добавя нов. Може ли някакво предложение как да се справя с този проблем?

EDIT: Мисля, че го оправих. Качвам нова версия.

Добрин обнови решението на 28.11.2016 22:44 (преди над 7 години)

module SubHashChecker
def sub_hash?(main_hash, sub_hash)
main_hash.merge(sub_hash) == main_hash
end
end
-
module DataModelSingletonMethods
def data_store(repository = nil)
if repository
@repository = repository
else
@repository
end
end
def attributes(*attribute_names)
if attribute_names.empty?
@attribute_names
else
@attribute_names = attribute_names
@attribute_names << :id
end
@attribute_names.each { |attribute| attr_accessor attribute }
end
def where(criteria)
check_for_invalid_keys(criteria, @attribute_names)
result = []
@repository.storage.each do |current_hash|
- result << self.new(current_hash) if sub_hash?(current_hash, criteria)
+ current_hash = current_hash[1] if current_hash.is_a? Array
+ add_to_result(result, current_hash) if sub_hash?(current_hash, criteria)
+ # new_instance = self.new(current_hash)
+ # new_instance.saved_to_repository = true
+ # result << new_instance
+ # end
end
result
end
-end
+ def add_to_result(result, current_hash_informations)
+ new_instance = self.new(current_hash_informations)
+ new_instance.saved_to_repository = true
+ result << new_instance
+ end
+end
module InitializeHelpers
def initialize_attributes(names, information_hash)
names.each do |attribute|
value = information_hash[attribute]
if value
send("#{attribute}=".to_sym, value)
else
send("#{attribute}=".to_sym, nil)
end
end
end
def initialize_singleton_finders(names, which_class)
names.each do |attribute|
which_class.define_singleton_method "find_by_#{attribute}".to_sym do |value|
hash_attribute = {attribute => value}
which_class.where(hash_attribute)
end
end
end
end
-
module Helpers
include SubHashChecker
include InitializeHelpers
-
def check_for_invalid_keys(criteria_hash, attribute_names)
criteria_hash.each do |key, _|
unless attribute_names.include?(key)
raise DataModel::UnknownAttributeError, "Unknown attribute #{key}"
end
end
end
def find_id_for_instance(instance, repository)
@id = 1
@id += 1 while repository.find({id: @id}) != []
instance[:id] = @id
repository.create(instance)
@saved_to_repository = true
end
end
-
class HashStore
include Helpers
attr_reader :storage
def initialize
@storage = {}
end
def create(information_hash)
id = information_hash[:id]
@storage[id] = information_hash
end
def find(search_hash)
result = []
@storage.each do |_, current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
id = current_hash[:id]
@storage.delete(id)
end
end
end
-
class ArrayStore
include Helpers
attr_reader :storage
def initialize
@storage = []
end
def create(information_hash)
@storage << information_hash
end
def find(search_hash)
result = []
@storage.each do |current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
storage.each do |current_hash|
if current_hash[:id] == id
desired_hash = current_hash
break
end
end
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
@storage.delete(current_hash)
end
end
end
-
class DataModel
include Helpers
extend Helpers
extend DataModelSingletonMethods
class DeleteUnsavedRecordError < RuntimeError; end
class UnknownAttributeError < RuntimeError; end
- attr_reader :saved_to_repository
-
+ attr_accessor :saved_to_repository
def initialize(information_hash = {})
names = self.class.instance_variable_get(:@attribute_names)
initialize_attributes(names, information_hash)
- @id = 1
+ @id ||= 1
@saved_to_repository = false
initialize_singleton_finders(names, self.class)
end
def hash_information
names = self.class.instance_variable_get(:@attribute_names)
result = {}
names.each do |attribute|
result[attribute] = send attribute
end
result.delete(:id)
result
end
def save
repository = self.class.instance_variable_get(:@repository)
instance = hash_information
if !@saved_to_repository
find_id_for_instance(instance, repository)
else
- repository.update(repository.find(instance)[0][:id], instance)
+ repository.update(repository.find({id: @id})[0][:id], instance)
end
self
end
def delete
repository = self.class.instance_variable_get(:@repository)
if repository.find(hash_information) == []
raise DeleteUnsavedRecordError
else
repository.delete(hash_information)
end
end
def ==(other)
return false unless other.instance_of?(self.class)
if @saved_to_repository && other.saved_to_repository && id == other.id
true
else
self.equal?(other)
end
end
end

Добрин обнови решението на 29.11.2016 12:20 (преди над 7 години)

module SubHashChecker
def sub_hash?(main_hash, sub_hash)
main_hash.merge(sub_hash) == main_hash
end
end
module DataModelSingletonMethods
def data_store(repository = nil)
if repository
@repository = repository
else
@repository
end
end
def attributes(*attribute_names)
if attribute_names.empty?
@attribute_names
else
@attribute_names = attribute_names
@attribute_names << :id
end
@attribute_names.each { |attribute| attr_accessor attribute }
end
def where(criteria)
check_for_invalid_keys(criteria, @attribute_names)
result = []
@repository.storage.each do |current_hash|
current_hash = current_hash[1] if current_hash.is_a? Array
add_to_result(result, current_hash) if sub_hash?(current_hash, criteria)
- # new_instance = self.new(current_hash)
- # new_instance.saved_to_repository = true
- # result << new_instance
- # end
end
result
end
def add_to_result(result, current_hash_informations)
new_instance = self.new(current_hash_informations)
new_instance.saved_to_repository = true
result << new_instance
end
end
module InitializeHelpers
def initialize_attributes(names, information_hash)
names.each do |attribute|
value = information_hash[attribute]
if value
send("#{attribute}=".to_sym, value)
else
send("#{attribute}=".to_sym, nil)
end
end
end
def initialize_singleton_finders(names, which_class)
names.each do |attribute|
which_class.define_singleton_method "find_by_#{attribute}".to_sym do |value|
hash_attribute = {attribute => value}
which_class.where(hash_attribute)
end
end
end
end
module Helpers
include SubHashChecker
include InitializeHelpers
def check_for_invalid_keys(criteria_hash, attribute_names)
criteria_hash.each do |key, _|
unless attribute_names.include?(key)
raise DataModel::UnknownAttributeError, "Unknown attribute #{key}"
end
end
end
def find_id_for_instance(instance, repository)
@id = 1
@id += 1 while repository.find({id: @id}) != []
instance[:id] = @id
repository.create(instance)
@saved_to_repository = true
end
end
class HashStore
include Helpers
attr_reader :storage
def initialize
@storage = {}
end
def create(information_hash)
id = information_hash[:id]
@storage[id] = information_hash
end
def find(search_hash)
result = []
@storage.each do |_, current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
id = current_hash[:id]
@storage.delete(id)
end
end
end
class ArrayStore
include Helpers
attr_reader :storage
def initialize
@storage = []
end
def create(information_hash)
@storage << information_hash
end
def find(search_hash)
result = []
@storage.each do |current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
storage.each do |current_hash|
if current_hash[:id] == id
desired_hash = current_hash
break
end
end
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
@storage.delete(current_hash)
end
end
end
class DataModel
include Helpers
extend Helpers
extend DataModelSingletonMethods
class DeleteUnsavedRecordError < RuntimeError; end
class UnknownAttributeError < RuntimeError; end
attr_accessor :saved_to_repository
def initialize(information_hash = {})
names = self.class.instance_variable_get(:@attribute_names)
initialize_attributes(names, information_hash)
- @id ||= 1
@saved_to_repository = false
initialize_singleton_finders(names, self.class)
end
def hash_information
names = self.class.instance_variable_get(:@attribute_names)
result = {}
names.each do |attribute|
result[attribute] = send attribute
end
result.delete(:id)
result
end
def save
repository = self.class.instance_variable_get(:@repository)
instance = hash_information
if !@saved_to_repository
find_id_for_instance(instance, repository)
else
repository.update(repository.find({id: @id})[0][:id], instance)
end
self
end
def delete
repository = self.class.instance_variable_get(:@repository)
if repository.find(hash_information) == []
raise DeleteUnsavedRecordError
else
repository.delete(hash_information)
end
end
def ==(other)
return false unless other.instance_of?(self.class)
if @saved_to_repository && other.saved_to_repository && id == other.id
true
else
self.equal?(other)
end
end
+end
+
+class User < DataModel
+ attributes :name, :email
+ data_store HashStore.new
end

Добрин обнови решението на 30.11.2016 15:27 (преди над 7 години)

module SubHashChecker
def sub_hash?(main_hash, sub_hash)
main_hash.merge(sub_hash) == main_hash
end
end
module DataModelSingletonMethods
def data_store(repository = nil)
if repository
@repository = repository
else
@repository
end
end
def attributes(*attribute_names)
if attribute_names.empty?
@attribute_names
else
@attribute_names = attribute_names
@attribute_names << :id
end
@attribute_names.each { |attribute| attr_accessor attribute }
end
def where(criteria)
check_for_invalid_keys(criteria, @attribute_names)
result = []
@repository.storage.each do |current_hash|
current_hash = current_hash[1] if current_hash.is_a? Array
add_to_result(result, current_hash) if sub_hash?(current_hash, criteria)
end
result
end
def add_to_result(result, current_hash_informations)
new_instance = self.new(current_hash_informations)
new_instance.saved_to_repository = true
result << new_instance
end
end
module InitializeHelpers
def initialize_attributes(names, information_hash)
names.each do |attribute|
value = information_hash[attribute]
if value
send("#{attribute}=".to_sym, value)
else
send("#{attribute}=".to_sym, nil)
end
end
end
def initialize_singleton_finders(names, which_class)
names.each do |attribute|
which_class.define_singleton_method "find_by_#{attribute}".to_sym do |value|
hash_attribute = {attribute => value}
which_class.where(hash_attribute)
end
end
end
end
module Helpers
include SubHashChecker
include InitializeHelpers
def check_for_invalid_keys(criteria_hash, attribute_names)
criteria_hash.each do |key, _|
unless attribute_names.include?(key)
raise DataModel::UnknownAttributeError, "Unknown attribute #{key}"
end
end
end
def find_id_for_instance(instance, repository)
- @id = 1
- @id += 1 while repository.find({id: @id}) != []
+ repository.max_used_id += 1
+ @id = repository.max_used_id
instance[:id] = @id
repository.create(instance)
@saved_to_repository = true
end
end
class HashStore
include Helpers
attr_reader :storage
+ attr_accessor :max_used_id
def initialize
@storage = {}
+ @max_used_id = 0
end
def create(information_hash)
id = information_hash[:id]
@storage[id] = information_hash
end
def find(search_hash)
result = []
@storage.each do |_, current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
id = current_hash[:id]
@storage.delete(id)
end
end
end
class ArrayStore
include Helpers
attr_reader :storage
+ attr_accessor :max_used_id
def initialize
@storage = []
+ @max_used_id = 0
end
def create(information_hash)
@storage << information_hash
end
def find(search_hash)
result = []
@storage.each do |current_hash|
result << current_hash if sub_hash?(current_hash, search_hash)
end
result
end
def update(id, to_overload)
desired_hash = storage[id]
storage.each do |current_hash|
if current_hash[:id] == id
desired_hash = current_hash
break
end
end
to_overload.each do |key, value|
desired_hash[key] = value
end
end
def delete(search_hash)
matches = find(search_hash)
matches.each do |current_hash|
@storage.delete(current_hash)
end
end
end
class DataModel
include Helpers
extend Helpers
extend DataModelSingletonMethods
class DeleteUnsavedRecordError < RuntimeError; end
class UnknownAttributeError < RuntimeError; end
attr_accessor :saved_to_repository
def initialize(information_hash = {})
names = self.class.instance_variable_get(:@attribute_names)
initialize_attributes(names, information_hash)
@saved_to_repository = false
initialize_singleton_finders(names, self.class)
end
def hash_information
names = self.class.instance_variable_get(:@attribute_names)
result = {}
names.each do |attribute|
result[attribute] = send attribute
end
result.delete(:id)
result
end
def save
repository = self.class.instance_variable_get(:@repository)
instance = hash_information
if !@saved_to_repository
find_id_for_instance(instance, repository)
else
repository.update(repository.find({id: @id})[0][:id], instance)
end
self
end
def delete
repository = self.class.instance_variable_get(:@repository)
if repository.find(hash_information) == []
raise DeleteUnsavedRecordError
else
repository.delete(hash_information)
+ @saved_to_repository = false
end
end
def ==(other)
return false unless other.instance_of?(self.class)
if @saved_to_repository && other.saved_to_repository && id == other.id
true
else
self.equal?(other)
end
end
-end
-
-class User < DataModel
- attributes :name, :email
- data_store HashStore.new
end