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

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

Към профила на Добромира Лозева

Резултати

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

Код

class DataModel
class << self
attr_reader :store
def attributes(*attrs)
@attributes = attrs
attrs.each do |name|
define_method(name) { @changed_values[name] }
define_method("#{name}=") { |val| @changed_values[name] = val }
define_singleton_method("find_by_#{name}") { |val| @store.find(name => val) }
end
end
def attrs
@attributes
end
def save_hashes
saved = {}
@objects.each_with_index { |item, index| saved[index + 1] = item }
end
def data_store(store)
@store = store
end
def where(params)
@store.find(params)
end
end
def initialize(args = {})
@values = {}
@changed_values = {}
args.each { |key, value| @values[key] = value if User.attrs.include?(key) }
end
def save
@changed_values.each { |key, value| @values[key] = value }
self.class.store.create(@values)
@changed_values = {}
self
end
def delete
self.class.store.delete(@values)
self
end
def attributes
@values.merge(@changed_values)
end
def changed_attributes
@changed_values
end
def changed_attributes=(new_value)
@changed_values = new_value
end
end
class HashStore
def initialize
@id = 0
@objects = {}
end
def getter
@objects
end
def id
@id += 1
end
def create(object)
existing = find(object).first
if existing
update(existing[:id], object)
else
object[:id] ||= id
@objects[object[:id]] = object
end
end
def find(params)
objects = @objects
objects.select do |_k, v|
params.all? do |key, value|
v[key] == value
end
end.values
end
def update(id, params)
obj = find({ id: id }).first
params.each do |key, value|
obj[key] = value
end
end
def delete(params)
@objects.delete_if do |k, _v|
params.all? do |key, value|
k[key] == value
end
end
end
end
class ArrayStore
def initialize
@id = 0
@objects = []
end
def getter
@objects
end
def id
@id += 1
end
def create(object)
existing = find(object).first
if existing
update(existing[:id], object)
else
object[:id] ||= id
@objects << object
end
end
def find(params)
objects = @objects
objects.select do |obj|
params.all? do |key, value|
obj[key] == value
end
end
end
def update(id, params)
obj = find({ id: id }).first
params.each do |key, value|
obj[key] = value
end
end
def delete(params)
@objects.delete_if do |obj|
params.all? do |key, value|
obj[key] == value
end
end
end
end

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

.FFFFFFFFFFFFFF....F.....

Failures:

  1) DataModel has attributes and data_model getters
     Failure/Error: expect(user_model.attributes).to include :first_name
       expected [] to include :first_name
       Diff:
       @@ -1,2 +1,2 @@
       -[:first_name]
       +[]
     # /tmp/d20161202-15620-gtpxps/spec.rb:22: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 accepts attributes when initializing
     Failure/Error: record = user_model.new(
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:28:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:28: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)>'

  3) DataModel has #find_by_<attribute> methods
     Failure/Error: record = user_model.new(first_name: 'Ivan', last_name: 'Ivanov')
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:40:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:40: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)>'

  4) DataModel id generation creates id on first save and does not change it
     Failure/Error: record = user_model.new(first_name: 'Ivan', last_name: 'Ivanov')
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:49:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:49: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 id generation does not reuse ids
     Failure/Error: ivan = user_model.new(first_name: 'Ivan')
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:63:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:63: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 id generation does not break when there are two models with the same store
     Failure/Error: ivan = user_model.new(first_name: 'Ivan')
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:81:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:81: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 equality comparison compares by id if both records are saved
     Failure/Error: ivan = user_model.new(first_name: 'Ivan')
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:93:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:93: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 equality comparison uses #equal? if there are no ids
     Failure/Error: first_user  = user_model.new(first_name: 'Ivan')
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:109:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:109: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 finds records by attributes
     Failure/Error: user_model.new(first_name: 'Ivan', last_name: 'Ivanov').save
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:119:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:119: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 finds records by multiple attributes
     Failure/Error: user_model.new(first_name: 'Ivan', last_name: 'Ivanov').save
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:119:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:119: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.where returns empty collection when nothing is found
     Failure/Error: user_model.new(first_name: 'Ivan', last_name: 'Ivanov').save
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:119:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:119: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.where raises an error if the query is by an unknown key
     Failure/Error: user_model.new(first_name: 'Ivan', last_name: 'Ivanov').save
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:119:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:119: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) DataModel#delete deletes only the record for which it is called
     Failure/Error: ivan = user_model.new(first_name: 'Ivan').save
     NameError:
       uninitialized constant DataModel::User
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `block in initialize'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:36:in `initialize'
     # /tmp/d20161202-15620-gtpxps/spec.rb:152:in `new'
     # /tmp/d20161202-15620-gtpxps/spec.rb:152: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) DataModel#delete raises an error if the record is not saved
     Failure/Error: DataModel::DeleteUnsavedRecordError
     NameError:
       uninitialized constant DataModel::DeleteUnsavedRecordError
     # /tmp/d20161202-15620-gtpxps/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)>'

  15) HashStore behaves like a data store #delete can delete multiple records with a single query
     Failure/Error: store.delete(name: 'Pesho')
     TypeError:
       no implicit conversion of Symbol into Integer
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-gtpxps/spec.rb:235
     # /tmp/d20161202-15620-gtpxps/solution.rb:108:in `[]'
     # /tmp/d20161202-15620-gtpxps/solution.rb:108:in `block (2 levels) in delete'
     # /tmp/d20161202-15620-gtpxps/solution.rb:107:in `each'
     # /tmp/d20161202-15620-gtpxps/solution.rb:107:in `all?'
     # /tmp/d20161202-15620-gtpxps/solution.rb:107:in `block in delete'
     # /tmp/d20161202-15620-gtpxps/solution.rb:106:in `delete_if'
     # /tmp/d20161202-15620-gtpxps/solution.rb:106:in `delete'
     # /tmp/d20161202-15620-gtpxps/spec.rb:227: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.03608 seconds
25 examples, 15 failures

Failed examples:

rspec /tmp/d20161202-15620-gtpxps/spec.rb:21 # DataModel has attributes and data_model getters
rspec /tmp/d20161202-15620-gtpxps/spec.rb:27 # DataModel accepts attributes when initializing
rspec /tmp/d20161202-15620-gtpxps/spec.rb:39 # DataModel has #find_by_<attribute> methods
rspec /tmp/d20161202-15620-gtpxps/spec.rb:48 # DataModel id generation creates id on first save and does not change it
rspec /tmp/d20161202-15620-gtpxps/spec.rb:62 # DataModel id generation does not reuse ids
rspec /tmp/d20161202-15620-gtpxps/spec.rb:74 # DataModel id generation does not break when there are two models with the same store
rspec /tmp/d20161202-15620-gtpxps/spec.rb:92 # DataModel equality comparison compares by id if both records are saved
rspec /tmp/d20161202-15620-gtpxps/spec.rb:108 # DataModel equality comparison uses #equal? if there are no ids
rspec /tmp/d20161202-15620-gtpxps/spec.rb:124 # DataModel.where finds records by attributes
rspec /tmp/d20161202-15620-gtpxps/spec.rb:129 # DataModel.where finds records by multiple attributes
rspec /tmp/d20161202-15620-gtpxps/spec.rb:138 # DataModel.where returns empty collection when nothing is found
rspec /tmp/d20161202-15620-gtpxps/spec.rb:142 # DataModel.where raises an error if the query is by an unknown key
rspec /tmp/d20161202-15620-gtpxps/spec.rb:151 # DataModel#delete deletes only the record for which it is called
rspec /tmp/d20161202-15620-gtpxps/spec.rb:162 # DataModel#delete raises an error if the record is not saved
rspec /tmp/d20161202-15620-gtpxps/spec.rb:218 # HashStore behaves like a data store #delete can delete multiple records with a single query

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

Добромира обнови решението на 01.12.2016 23:12 (преди около 8 години)

+class DataModel
+ class << self
+ attr_reader :store
+
+ def attributes(*attrs)
+ @attributes = attrs
+
+ attrs.each do |name|
+ define_method(name) { @values[name] }
+ define_method("#{name}=") { |val| @changed_values[name] = val }
+ define_singleton_method("find_by_#{name}") { |val| @store.find(name => val) }
+ end
+ end
+
+ def attrs
+ @attributes
+ end
+
+ def save_hashes
+ saved = {}
+ @objects.each_with_index { |item, index| saved[index + 1] = item }
+ end
+
+ def data_store(store)
+ @store = store
+ end
+
+ def where(params)
+ @store.find(params)
+ end
+ end
+
+ def initialize(args = {})
+ @values = {}
+ @changed_values = {}
+ args.each { |key, value| @values[key] = value if User.attrs.include?(key) }
+ end
+
+ def save
+ @changed_values.each { |key, value| @values[key] = value }
+ self.class.store.create(@values)
+ @changed_values = {}
+ self
+ end
+
+ def delete
+ self.class.store.delete(@values)
+ self
+ end
+
+ def attributes
+ @values.merge(@changed_values)
+ end
+
+ def changed_attributes
+ @changed_values
+ end
+
+ def changed_attributes=(new_value)
+ @changed_values = new_value
+ end
+end
+
+class HashStore
+ def initialize
+ @id = 0
+ @objects = {}
+ end
+
+ def getter
+ @objects
+ end
+
+ def id
+ @id += 1
+ end
+
+ def create(object)
+ if object[:id]
+ update(object[:id], object)
+ else
+ object[:id] = id
+ @objects[object[:id]] = object
+ end
+ end
+
+ def find(params)
+ objects = @objects
+ objects.select do |_k, v|
+ params.all? do |key, value|
+ v[key] == value
+ end
+ end
+ end
+
+ def update(id, params)
+ obj = find({ id: id }).first
+ params.each do |key, value|
+ obj[key] = value
+ end
+ end
+
+ def delete(params)
+ @objects.delete_if do |k, _v|
+ params.all? do |key, value|
+ k[key] == value
+ end
+ end
+ end
+end
+
+class ArrayStore
+ def initialize
+ @id = 0
+ @objects = []
+ end
+
+ def getter
+ @objects
+ end
+
+ def id
+ @id += 1
+ end
+
+ def create(object)
+ if object[:id]
+ update(object[:id], object)
+ else
+ object[:id] = id
+ @objects << object
+ end
+ end
+
+ def find(params)
+ objects = @objects
+ objects.select do |obj|
+ params.all? do |key, value|
+ obj[key] == value
+ end
+ end
+ end
+
+ def update(id, params)
+ obj = find({ id: id }).first
+ params.each do |key, value|
+ obj[key] = value
+ end
+ end
+
+ def delete(params)
+ @objects.delete_if do |obj|
+ params.all? do |key, value|
+ obj[key] == value
+ end
+ end
+ end
+end

Добромира обнови решението на 01.12.2016 23:45 (преди около 8 години)

class DataModel
class << self
attr_reader :store
def attributes(*attrs)
@attributes = attrs
attrs.each do |name|
- define_method(name) { @values[name] }
+ define_method(name) { @changed_values[name] }
define_method("#{name}=") { |val| @changed_values[name] = val }
define_singleton_method("find_by_#{name}") { |val| @store.find(name => val) }
end
end
def attrs
@attributes
end
def save_hashes
saved = {}
@objects.each_with_index { |item, index| saved[index + 1] = item }
end
def data_store(store)
@store = store
end
def where(params)
@store.find(params)
end
end
def initialize(args = {})
@values = {}
@changed_values = {}
args.each { |key, value| @values[key] = value if User.attrs.include?(key) }
end
def save
@changed_values.each { |key, value| @values[key] = value }
self.class.store.create(@values)
@changed_values = {}
self
end
def delete
self.class.store.delete(@values)
self
end
def attributes
@values.merge(@changed_values)
end
def changed_attributes
@changed_values
end
def changed_attributes=(new_value)
@changed_values = new_value
end
end
class HashStore
def initialize
@id = 0
@objects = {}
end
def getter
@objects
end
def id
@id += 1
end
def create(object)
- if object[:id]
- update(object[:id], object)
+ existing = find(object).first
+ if existing
+ update(existing[:id], object)
else
- object[:id] = id
+ object[:id] ||= id
@objects[object[:id]] = object
end
end
def find(params)
objects = @objects
+
objects.select do |_k, v|
params.all? do |key, value|
v[key] == value
end
- end
+ end.values
end
def update(id, params)
obj = find({ id: id }).first
params.each do |key, value|
obj[key] = value
end
end
def delete(params)
@objects.delete_if do |k, _v|
params.all? do |key, value|
k[key] == value
end
end
end
end
class ArrayStore
def initialize
@id = 0
@objects = []
end
def getter
@objects
end
def id
@id += 1
end
def create(object)
- if object[:id]
- update(object[:id], object)
+ existing = find(object).first
+ if existing
+ update(existing[:id], object)
else
- object[:id] = id
+ object[:id] ||= id
@objects << object
end
end
def find(params)
objects = @objects
objects.select do |obj|
params.all? do |key, value|
obj[key] == value
end
end
end
def update(id, params)
obj = find({ id: id }).first
params.each do |key, value|
obj[key] = value
end
end
def delete(params)
@objects.delete_if do |obj|
params.all? do |key, value|
obj[key] == value
end
end
end
end