Решение на Пета задача - DataModel от Теодор Филипов

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

Към профила на Теодор Филипов

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 21 успешни тест(а)
  • 4 неуспешни тест(а)

Код

module DataModelClassMethods
def id
@id = 1 if @id.nil?
@id += 1
@id - 1
end
def where(a_pattern)
raise UnknownAttributeError unless a_pattern.all? do |key, _|
attributes.include? key
end
data_store.find(a_pattern).map do |h|
model = self.new h
model.id = h[:id]
model
end
end
def attributes(*a_attributes)
return @attributes if a_attributes.empty?
@attributes = a_attributes
generate_methods
end
def generate_methods
attributes.each do |attr|
define_method(attr.to_sym) { instance_variable_get("@#{attr}") }
define_method((attr.to_s + '=').to_sym) do |value|
instance_variable_set("@#{attr}", value)
end
define_singleton_method("find_by_#{attr}".to_sym) do |value|
where({attr.to_sym => value})
end
end
end
def data_store(a_store = @store)
@store = a_store
end
end
class DataModel
attr_accessor :id
extend DataModelClassMethods
def initialize(a_hash = {})
a_hash.select { |key, _| attributes.include? key }
.each { |key, value| send("#{key}=", value) }
end
def ==(model)
return false if model.id.nil? && id.nil? && (model.object_id != self.object_id)
return true if (model.instance_of? self.class) && (model.id == id)
false
end
def attributes
self.class.attributes
end
def data_store
self.class.data_store
end
def save
@id = self.class.id if @id.nil?
record_map = populate_record_map
if !storage_contains_id?(@id)
data_store.create record_map
else
data_store.update @id, record_map
end
end
def delete
raise DataModel::DeleteUnsavedRecordError if @id.nil?
data_store.delete(populate_record_map)
end
private
def storage_contains_id?(id)
return true unless data_store.find({id: id}).empty?
false
end
def populate_record_map
map = {}
attributes.map { |attribute| map[attribute] = send(attribute.to_sym) }
map[:id] = @id
map.delete(:attributes)
map.delete(:store)
map
end
class DeleteUnsavedRecordError < StandardError; end
class UnknownAttributeError < StandardError; end
end
class DataStore
def update(a_id, a_pattern)
end
def create(a_record)
end
def find(a_pattern)
end
def delete(a_pattern)
end
private
def record_matches_pattern?(a_record, a_pattern)
return false if a_record.nil?
a_record.select { |key, _| a_pattern.key? key }.eql? a_pattern
end
end
class ArrayStore < DataStore
def initialize
@array_store = []
@id = 1
end
def storage
@array_store
end
def create(a_record)
@array_store[a_record[:id]] = a_record
end
def find(a_pattern)
@array_store.select { |record| record_matches_pattern? record, a_pattern }
end
def update(a_id, a_record)
@array_store[a_id] = a_record
end
def delete(a_pattern)
@array_store.select { |record| record_matches_pattern? record, a_pattern }
.map { |record| record[:id] }.each { |id| @array_store[id] = nil }
end
end
class HashStore < DataStore
def initialize
@hash_store = {}
end
def storage
@hash_store
end
def create(a_record)
@hash_store[a_record[:id]] = a_record
end
def find(a_pattern)
@hash_store.select { |_, record| record_matches_pattern? record, a_pattern }
.map { |_, record| record }
end
def update(a_id, a_record)
@hash_store[a_id] = a_record
end
def delete(a_pattern)
@hash_store.select { |_, record| record_matches_pattern? record, a_pattern }
.map { |_, record| record[:id] }.each { |id| @hash_store.delete id }
end
end

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

......FF....FF...........

Failures:

  1) DataModel id generation does not break when there are two models with the same store
     Failure/Error: expect(picture.id).to eq 2
       
       expected: 2
            got: 1
       
       (compared using ==)
     # /tmp/d20161202-15620-1d6tz3k/spec.rb:87: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)>'

  2) DataModel equality comparison compares by id if both records are saved
     Failure/Error: modified_ivan = user_model.where(id: ivan.id).first
     NameError:
       uninitialized constant DataModelClassMethods::UnknownAttributeError
     # /tmp/d20161202-15620-1d6tz3k/solution.rb:9:in `where'
     # /tmp/d20161202-15620-1d6tz3k/spec.rb:102: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)>'

  3) 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 #<NameError: uninitialized constant DataModelClassMethods::UnknownAttributeError> with backtrace:
         # /tmp/d20161202-15620-1d6tz3k/solution.rb:9:in `where'
         # /tmp/d20161202-15620-1d6tz3k/spec.rb:143:in `block (4 levels) in <top (required)>'
         # /tmp/d20161202-15620-1d6tz3k/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-1d6tz3k/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)>'

  4) DataModel#delete deletes only the record for which it is called
     Failure/Error: ivan.delete
     ArgumentError:
       wrong number of arguments (given 0, expected 1)
     # /tmp/d20161202-15620-1d6tz3k/spec.rb:156:in `delete'
     # /tmp/d20161202-15620-1d6tz3k/spec.rb:156: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.02443 seconds
25 examples, 4 failures

Failed examples:

rspec /tmp/d20161202-15620-1d6tz3k/spec.rb:74 # DataModel id generation does not break when there are two models with the same store
rspec /tmp/d20161202-15620-1d6tz3k/spec.rb:92 # DataModel equality comparison compares by id if both records are saved
rspec /tmp/d20161202-15620-1d6tz3k/spec.rb:142 # DataModel.where raises an error if the query is by an unknown key
rspec /tmp/d20161202-15620-1d6tz3k/spec.rb:151 # DataModel#delete deletes only the record for which it is called

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

Теодор обнови решението на 01.12.2016 04:22 (преди около 8 години)

+module DataModelClassMethods
+ def where(a_pattern)
+ raise UnknownAttributeError unless a_pattern.all? do |key, _|
+ attributes.include? key
+ end
+ data_store.find(a_pattern).map do |h|
+ model = self.new h
+ model.id = h[:id]
+ model
+ end
+ end
+
+ def attributes(*a_attributes)
+ return @attributes if a_attributes.empty?
+ @attributes = a_attributes
+ generate_methods
+ end
+
+ def generate_methods
+ attributes.each do |attr|
+ define_method(attr.to_sym) { instance_variable_get("@#{attr}") }
+ define_method((attr.to_s + '=').to_sym) do |value|
+ instance_variable_set("@#{attr}", value)
+ end
+ define_singleton_method("find_by_#{attr}".to_sym) do |value|
+ where({attr.to_sym => value})
+ end
+ end
+ end
+
+ def data_store(a_store = @store)
+ @store = a_store
+ end
+end
+
+class DataModel
+ attr_accessor :id
+
+ extend DataModelClassMethods
+ def initialize(a_hash = {})
+ a_hash.select { |key, _| attributes.include? key }
+ .each { |key, value| send("#{key}=", value) }
+ end
+
+ def ==(model)
+ return false if model.id.nil? && id.nil? && (model.object_id != self.object_id)
+ return true if (model.instance_of? self.class) && (model.id == id)
+ false
+ end
+
+ def attributes
+ self.class.attributes
+ end
+
+ def data_store
+ self.class.data_store
+ end
+
+ def save
+ record_map = populate_record_map
+ if !storage_contains_id?(@id)
+ @id = data_store.create record_map
+ else
+ data_store.update @id, record_map
+ end
+ end
+
+ def delete
+ raise DataModel::DeleteUnsavedRecordError if @id.nil?
+ data_store.delete(populate_record_map)
+ end
+
+ private
+ def storage_contains_id?(id)
+ return true unless data_store.find({id: id}).empty?
+ false
+ end
+
+ def populate_record_map
+ map = {}
+ attributes.map { |attribute| map[attribute] = send(attribute.to_sym) }
+ map.delete(:attributes)
+ map.delete(:store)
+ map
+ end
+
+ class DeleteUnsavedRecordError < StandardError; end
+ class UnknownAttributeError < StandardError; end
+end
+
+class DataStore
+ def delete(a_pattern)
+ end
+
+ private
+
+ def record_matches_pattern?(a_record, a_pattern)
+ return false if a_record.nil?
+ a_record.select { |key, _| a_pattern.key? key }.eql? a_pattern
+ end
+
+ def create(a_record)
+ a_record[:id] = @id
+ storage[@id] = a_record
+ @id += 1
+ end
+
+ def find(a_pattern)
+ storage.select { |record| record_matches_pattern? record, a_pattern }
+ end
+
+ def update(a_id, a_record)
+ storage[a_id] = a_record
+ end
+end
+
+class ArrayStore < DataStore
+ def initialize
+ @array_store = []
+ @id = 1
+ end
+
+ def storage
+ @array_store
+ end
+
+ def create(a_record)
+ a_record[:id] = @id
+ @array_store[@id] = a_record
+ @id += 1
+ @id - 1
+ end
+
+ def find(a_pattern)
+ @array_store.select { |record| record_matches_pattern? record, a_pattern }
+ end
+
+ def update(a_id, a_record)
+ @array_store[a_id] = a_record
+ end
+
+ def delete(a_pattern)
+ @array_store.select { |record| record_matches_pattern? record, a_pattern }
+ .map { |record| record[:id] }.each { |id| @array_store[id] = nil }
+ end
+end
+
+class HashStore < DataStore
+ def initialize
+ @hash_store = {}
+ @id = 1
+ end
+
+ def storage
+ @hash_store
+ end
+
+ def create(a_record)
+ a_record[:id] = @id
+ @hash_store[@id] = a_record
+ @id += 1
+ @id - 1
+ end
+
+ def find(a_pattern)
+ @hash_store.select { |_, record| record_matches_pattern? record, a_pattern }
+ .map { |_, record| record }
+ end
+
+ def update(a_id, a_record)
+ @hash_store[a_id] = a_record
+ end
+
+ def delete(a_pattern)
+ @hash_store.select { |_, record| record_matches_pattern? record, a_pattern }
+ .map { |_, record| record[:id] }.each { |id| @hash_store.delete id }
+ end
+end

Теодор обнови решението на 01.12.2016 18:08 (преди около 8 години)

module DataModelClassMethods
+ def id
+ @id = 1 if @id.nil?
+ @id += 1
+ @id - 1
+ end
+
def where(a_pattern)
raise UnknownAttributeError unless a_pattern.all? do |key, _|
attributes.include? key
end
data_store.find(a_pattern).map do |h|
model = self.new h
model.id = h[:id]
model
end
end
def attributes(*a_attributes)
return @attributes if a_attributes.empty?
@attributes = a_attributes
generate_methods
end
def generate_methods
attributes.each do |attr|
define_method(attr.to_sym) { instance_variable_get("@#{attr}") }
define_method((attr.to_s + '=').to_sym) do |value|
instance_variable_set("@#{attr}", value)
end
define_singleton_method("find_by_#{attr}".to_sym) do |value|
where({attr.to_sym => value})
end
end
end
def data_store(a_store = @store)
@store = a_store
end
end
class DataModel
attr_accessor :id
extend DataModelClassMethods
def initialize(a_hash = {})
a_hash.select { |key, _| attributes.include? key }
.each { |key, value| send("#{key}=", value) }
end
def ==(model)
return false if model.id.nil? && id.nil? && (model.object_id != self.object_id)
return true if (model.instance_of? self.class) && (model.id == id)
false
end
def attributes
self.class.attributes
end
def data_store
self.class.data_store
end
def save
+ @id = self.class.id if @id.nil?
record_map = populate_record_map
if !storage_contains_id?(@id)
- @id = data_store.create record_map
+ data_store.create record_map
else
data_store.update @id, record_map
end
end
def delete
raise DataModel::DeleteUnsavedRecordError if @id.nil?
data_store.delete(populate_record_map)
end
private
def storage_contains_id?(id)
return true unless data_store.find({id: id}).empty?
false
end
def populate_record_map
map = {}
attributes.map { |attribute| map[attribute] = send(attribute.to_sym) }
+ map[:id] = @id
map.delete(:attributes)
map.delete(:store)
map
end
class DeleteUnsavedRecordError < StandardError; end
class UnknownAttributeError < StandardError; end
end
class DataStore
+ def update(a_id, a_pattern)
+ end
+
+ def create(a_record)
+ end
+
+ def find(a_pattern)
+ end
+
def delete(a_pattern)
end
private
def record_matches_pattern?(a_record, a_pattern)
return false if a_record.nil?
a_record.select { |key, _| a_pattern.key? key }.eql? a_pattern
end
-
- def create(a_record)
- a_record[:id] = @id
- storage[@id] = a_record
- @id += 1
- end
-
- def find(a_pattern)
- storage.select { |record| record_matches_pattern? record, a_pattern }
- end
-
- def update(a_id, a_record)
- storage[a_id] = a_record
- end
end
class ArrayStore < DataStore
def initialize
@array_store = []
@id = 1
end
def storage
@array_store
end
def create(a_record)
- a_record[:id] = @id
- @array_store[@id] = a_record
- @id += 1
- @id - 1
+ @array_store[a_record[:id]] = a_record
end
def find(a_pattern)
@array_store.select { |record| record_matches_pattern? record, a_pattern }
end
def update(a_id, a_record)
@array_store[a_id] = a_record
end
def delete(a_pattern)
@array_store.select { |record| record_matches_pattern? record, a_pattern }
.map { |record| record[:id] }.each { |id| @array_store[id] = nil }
end
end
class HashStore < DataStore
def initialize
@hash_store = {}
- @id = 1
end
def storage
@hash_store
end
def create(a_record)
- a_record[:id] = @id
- @hash_store[@id] = a_record
- @id += 1
- @id - 1
+ @hash_store[a_record[:id]] = a_record
end
def find(a_pattern)
@hash_store.select { |_, record| record_matches_pattern? record, a_pattern }
.map { |_, record| record }
end
def update(a_id, a_record)
@hash_store[a_id] = a_record
end
def delete(a_pattern)
@hash_store.select { |_, record| record_matches_pattern? record, a_pattern }
.map { |_, record| record[:id] }.each { |id| @hash_store.delete id }
end
end