Решение на Пета задача - DataModel от Кристъфър Коруев

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

Към профила на Кристъфър Коруев

Резултати

  • 2 точки от тестове
  • 0 бонус точки
  • 2 точки общо
  • 7 успешни тест(а)
  • 18 неуспешни тест(а)

Код

class Store
attr_accessor :id
def create(hash)
end
def find(query)
end
def update(id)
end
def delete(query)
end
end
class ArrayStore < Store
def initialize
@array_store = []
@id = 0
end
def create(hash)
@id = hash[:id]
@array_store.push(hash)
@id += 1
nil
end
def find(query)
return [] if query.empty?
keys = query.keys
find_entries(@array_store, query, keys, keys.shift)
end
def update(id, attributes)
hash_to_update = {}
@array_store.each do |entry|
hash_to_update = entry if entry[:id] == id
end
attributes.keys.each do |key|
hash_to_update[key] = attributes[key]
end
end
def delete(query)
return [] if query.empty?
keys = query.keys
entries_to_delete = find_entries(@array_store, query, keys, keys.shift)
entries_to_delete.each do |entry|
@array_store.delete(entry)
end
end
def storage
@array_store
end
private
def find_entries(all_entries, query, keys, param)
temp_array = []
all_entries.each do |entry|
temp_array.push(entry) if query[param] == entry[param]
end
return temp_array if keys.empty?
next_param = keys.shift
find_entries(temp_array, query, keys, next_param)
end
end
class HashStore < Store
def initialize
@hash_store = {}
end
def storage
@hash_store
end
end
class DataModel
def initialize(arguments = {})
self.class.get_attributes.each do |attribute|
send "#{attribute}=", arguments[attribute]
end
end
def save
return save_entry if @id.nil?
upload_entry
end
def ==(other_obj)
return false unless self.class == other_obj.class
true
end
def self.attributes(*attributes)
defined_attributes = (defined? self.get_attributes).nil?
return self.get_attributes if attributes.empty? && !defined_attributes
attributes.each do |attribute|
attr_accessor attribute
end
attr_accessor :id
self.define_singleton_method(:get_attributes) do
attributes
end
end
def self.data_store(store = nil)
return self.get_store if defined? self.get_store
self.define_singleton_method(:get_store) do
store
end
end
private
def save_entry
store = self.class.get_store
hash = {}
self.id = store.id
self.id = 0 if self.id.nil?
self.class.get_attributes.each do |attribute|
hash[attribute] = send attribute.to_s
end
hash[:id] = self.id
store.create(hash)
end
def upload_entry
store = self.class.get_store
hash = {}
self.class.get_attributes.each do |attribute|
hash[attribute] = send attribute.to_s
end
store.update(self.id, hash)
end
end

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

...FFFFFFFFFFFFFFFFF....F

Failures:

  1) DataModel has #find_by_<attribute> methods
     Failure/Error: expect(user_model.find_by_first_name('Ivan').map(&:id)).to eq [record.id]
     NoMethodError:
       undefined method `find_by_first_name' for #<Class:0x007f408ef041c0>
     # /tmp/d20161202-15620-1k68syw/spec.rb:43:in `block (2 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 id generation creates id on first save and does not change it
     Failure/Error: record.save
     ArgumentError:
       wrong number of arguments (given 2, expected 1)
     # /tmp/d20161202-15620-1k68syw/solution.rb:10:in `update'
     # /tmp/d20161202-15620-1k68syw/solution.rb:139:in `upload_entry'
     # /tmp/d20161202-15620-1k68syw/solution.rb:92:in `save'
     # /tmp/d20161202-15620-1k68syw/spec.rb:57: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 id generation does not reuse ids
     Failure/Error: expect(ivan.id).to eq 1
       
       expected: 1
            got: 0
       
       (compared using ==)
     # /tmp/d20161202-15620-1k68syw/spec.rb:65: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 id generation does not break when there are two models with the same store
     Failure/Error: expect(ivan.id).to eq 1
       
       expected: 1
            got: 0
       
       (compared using ==)
     # /tmp/d20161202-15620-1k68syw/spec.rb:83: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)>'

  5) DataModel equality comparison compares by id if both records are saved
     Failure/Error: expect(ivan).to_not eq petar
       
       expected: value != #<#<Class:0x007f408ed5ba08>:0x007f408ed5a6f8 @first_name="Petar", @last_name=nil, @age=nil, @id=0>
            got: #<#<Class:0x007f408ed5ba08>:0x007f408ed5ab30 @first_name="Ivan", @last_name=nil, @age=nil, @id=0>
       
       (compared using ==)
       
       Diff:
       
       @@ -1,6 +1,6 @@
       -#<#<Class:0x007f408ed5ba08>:0x007f408ed5a6f8
       +#<#<Class:0x007f408ed5ba08>:0x007f408ed5ab30
         @age=nil,
       - @first_name="Petar",
       + @first_name="Ivan",
         @id=0,
         @last_name=nil>
     # /tmp/d20161202-15620-1k68syw/spec.rb:99: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)>'

  6) DataModel equality comparison uses #equal? if there are no ids
     Failure/Error: expect(first_user).to_not eq second_user
       
       expected: value != #<#<Class:0x007f408fa78970>:0x007f408fa77f48 @first_name="Ivan", @last_name=nil, @age=nil>
            got: #<#<Class:0x007f408fa78970>:0x007f408fa78060 @first_name="Ivan", @last_name=nil, @age=nil>
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,4 @@
       -#<#<Class:0x007f408fa78970>:0x007f408fa77f48
       +#<#<Class:0x007f408fa78970>:0x007f408fa78060
         @age=nil,
         @first_name="Ivan",
         @last_name=nil>
     # /tmp/d20161202-15620-1k68syw/spec.rb:112: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)>'

  7) DataModel.where finds records by attributes
     Failure/Error: records = user_model.where(first_name: 'Ivan').map(&:last_name)
     NoMethodError:
       undefined method `where' for #<Class:0x007f408fa52b58>
     # /tmp/d20161202-15620-1k68syw/spec.rb:125: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)>'

  8) DataModel.where finds records by multiple attributes
     Failure/Error: records = user_model.where(
     NoMethodError:
       undefined method `where' for #<Class:0x007f408fa4ea30>
     # /tmp/d20161202-15620-1k68syw/spec.rb:130: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)>'

  9) DataModel.where returns empty collection when nothing is found
     Failure/Error: expect(user_model.where(first_name: 'Petar')).to be_empty
     NoMethodError:
       undefined method `where' for #<Class:0x007f408fa41fb0>
     # /tmp/d20161202-15620-1k68syw/spec.rb:139: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)>'

  10) DataModel.where raises an error if the query is by an unknown key
     Failure/Error: DataModel::UnknownAttributeError,
     NameError:
       uninitialized constant DataModel::UnknownAttributeError
     # /tmp/d20161202-15620-1k68syw/spec.rb:144: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)>'

  11) DataModel#delete deletes only the record for which it is called
     Failure/Error: ivan.delete
     NoMethodError:
       undefined method `delete' for nil:NilClass
     # /tmp/d20161202-15620-1k68syw/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)>'

  12) DataModel#delete raises an error if the record is not saved
     Failure/Error: DataModel::DeleteUnsavedRecordError
     NameError:
       uninitialized constant DataModel::DeleteUnsavedRecordError
     # /tmp/d20161202-15620-1k68syw/spec.rb:164: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)>'

  13) HashStore behaves like a data store #create saves a new record
     Failure/Error: expect(store.find(id: 2)).to eq [user]
       
       expected: [{:id=>2, :name=>"Pesho"}]
            got: nil
       
       (compared using ==)
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-1k68syw/spec.rb:235
     # /tmp/d20161202-15620-1k68syw/spec.rb:178: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)>'

  14) HashStore behaves like a data store #find can find elements by attributes
     Failure/Error: expect(store.find(id: 2)).to eq [user]
       
       expected: [{:id=>2, :name=>"Pesho"}]
            got: nil
       
       (compared using ==)
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-1k68syw/spec.rb:235
     # /tmp/d20161202-15620-1k68syw/spec.rb:187: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)>'

  15) HashStore behaves like a data store #update updates the attributes of a record with a given ID
     Failure/Error: store.update(2, {id: 2, name: 'Georgi'})
     ArgumentError:
       wrong number of arguments (given 2, expected 1)
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-1k68syw/spec.rb:235
     # /tmp/d20161202-15620-1k68syw/solution.rb:10:in `update'
     # /tmp/d20161202-15620-1k68syw/spec.rb:199: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)>'

  16) HashStore behaves like a data store #update only updates records with the correct IDs
     Failure/Error: store.update(2, {id: 2, name: 'Sasho'})
     ArgumentError:
       wrong number of arguments (given 2, expected 1)
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-1k68syw/spec.rb:235
     # /tmp/d20161202-15620-1k68syw/solution.rb:10:in `update'
     # /tmp/d20161202-15620-1k68syw/spec.rb:210: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)>'

  17) HashStore behaves like a data store #delete can delete multiple records with a single query
     Failure/Error: expect(store.find({})).to eq [gosho]
       
       expected: [{:id=>3, :name=>"Gosho"}]
            got: nil
       
       (compared using ==)
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-1k68syw/spec.rb:235
     # /tmp/d20161202-15620-1k68syw/spec.rb:229: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)>'

  18) ArrayStore behaves like a data store #delete can delete multiple records with a single query
     Failure/Error: expect(store.find({})).to eq [gosho]
       
       expected: [{:id=>3, :name=>"Gosho"}]
            got: []
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -[{:id=>3, :name=>"Gosho"}]
       +[]
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-1k68syw/spec.rb:239
     # /tmp/d20161202-15620-1k68syw/spec.rb:229: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.03194 seconds
25 examples, 18 failures

Failed examples:

rspec /tmp/d20161202-15620-1k68syw/spec.rb:39 # DataModel has #find_by_<attribute> methods
rspec /tmp/d20161202-15620-1k68syw/spec.rb:48 # DataModel id generation creates id on first save and does not change it
rspec /tmp/d20161202-15620-1k68syw/spec.rb:62 # DataModel id generation does not reuse ids
rspec /tmp/d20161202-15620-1k68syw/spec.rb:74 # DataModel id generation does not break when there are two models with the same store
rspec /tmp/d20161202-15620-1k68syw/spec.rb:92 # DataModel equality comparison compares by id if both records are saved
rspec /tmp/d20161202-15620-1k68syw/spec.rb:108 # DataModel equality comparison uses #equal? if there are no ids
rspec /tmp/d20161202-15620-1k68syw/spec.rb:124 # DataModel.where finds records by attributes
rspec /tmp/d20161202-15620-1k68syw/spec.rb:129 # DataModel.where finds records by multiple attributes
rspec /tmp/d20161202-15620-1k68syw/spec.rb:138 # DataModel.where returns empty collection when nothing is found
rspec /tmp/d20161202-15620-1k68syw/spec.rb:142 # DataModel.where raises an error if the query is by an unknown key
rspec /tmp/d20161202-15620-1k68syw/spec.rb:151 # DataModel#delete deletes only the record for which it is called
rspec /tmp/d20161202-15620-1k68syw/spec.rb:162 # DataModel#delete raises an error if the record is not saved
rspec /tmp/d20161202-15620-1k68syw/spec.rb:174 # HashStore behaves like a data store #create saves a new record
rspec /tmp/d20161202-15620-1k68syw/spec.rb:183 # HashStore behaves like a data store #find can find elements by attributes
rspec /tmp/d20161202-15620-1k68syw/spec.rb:196 # HashStore behaves like a data store #update updates the attributes of a record with a given ID
rspec /tmp/d20161202-15620-1k68syw/spec.rb:204 # HashStore behaves like a data store #update only updates records with the correct IDs
rspec /tmp/d20161202-15620-1k68syw/spec.rb:218 # HashStore behaves like a data store #delete can delete multiple records with a single query
rspec /tmp/d20161202-15620-1k68syw/spec.rb:218 # ArrayStore behaves like a data store #delete can delete multiple records with a single query

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

Кристъфър обнови решението на 01.12.2016 23:21 (преди над 7 години)

+class Store
+ attr_accessor :id
+
+ def create(hash)
+ end
+
+ def find(query)
+ end
+
+ def update(id)
+ end
+
+ def delete(query)
+ end
+end
+
+class ArrayStore < Store
+ def initialize
+ @array_store = []
+ @id = 0
+ end
+
+ def create(hash)
+ @id = hash[:id]
+ @array_store.push(hash)
+ @id += 1
+ nil
+ end
+
+ def find(query)
+ return [] if query.empty?
+ keys = query.keys
+ find_entries(@array_store, query, keys, keys.shift)
+ end
+
+ def update(id, attributes)
+ hash_to_update = {}
+ @array_store.each do |entry|
+ hash_to_update = entry if entry[:id] == id
+ end
+
+ attributes.keys.each do |key|
+ hash_to_update[key] = attributes[key]
+ end
+ end
+
+ def delete(query)
+ return [] if query.empty?
+ keys = query.keys
+ entries_to_delete = find_entries(@array_store, query, keys, keys.shift)
+ entries_to_delete.each do |entry|
+ @array_store.delete(entry)
+ end
+ end
+
+ def storage
+ @array_store
+ end
+
+ private
+
+ def find_entries(all_entries, query, keys, param)
+ temp_array = []
+ all_entries.each do |entry|
+ temp_array.push(entry) if query[param] == entry[param]
+ end
+ return temp_array if keys.empty?
+ next_param = keys.shift
+ find_entries(temp_array, query, keys, next_param)
+ end
+end
+
+class HashStore < Store
+ def initialize
+ @hash_store = {}
+ end
+
+ def storage
+ @hash_store
+ end
+end
+
+class DataModel
+ def initialize(arguments = {})
+ self.class.get_attributes.each do |attribute|
+ send "#{attribute}=", arguments[attribute]
+ end
+ end
+
+ def save
+ return save_entry if @id.nil?
+ upload_entry
+ end
+
+ def ==(other_obj)
+ return false unless self.class == other_obj.class
+ true
+ end
+
+ def self.attributes(*attributes)
+ defined_attributes = (defined? self.get_attributes).nil?
+ return self.get_attributes if attributes.empty? && !defined_attributes
+ attributes.each do |attribute|
+ attr_accessor attribute
+ end
+ attr_accessor :id
+ self.define_singleton_method(:get_attributes) do
+ attributes
+ end
+ end
+
+ def self.data_store(store = nil)
+ return self.get_store if defined? self.get_store
+ self.define_singleton_method(:get_store) do
+ store
+ end
+ end
+
+ private
+
+ def save_entry
+ store = self.class.get_store
+ hash = {}
+ self.id = store.id
+ self.id = 0 if self.id.nil?
+ self.class.get_attributes.each do |attribute|
+ hash[attribute] = send attribute.to_s
+ end
+ hash[:id] = self.id
+ store.create(hash)
+ end
+
+ def upload_entry
+ store = self.class.get_store
+ hash = {}
+ self.class.get_attributes.each do |attribute|
+ hash[attribute] = send attribute.to_s
+ end
+ store.update(self.id, hash)
+ end
+end