Решение на Пета задача - DataModel от Калина Бухлева

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

Към профила на Калина Бухлева

Резултати

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

Код

module DataModelBasic
def save
store.create(self.convert)
self
end
def delete
raise DeleteUnsavedRecordError unless id
store.delete(self.convert)
self
end
def ==(other_object)
return false if self.class != other_object.class
return true if self.id == other_object.id
self.object_id == other_object.object_id
end
def convert
hsh = {}
store.counter = counter + 1 unless @id
@id = counter unless @id
hsh[:id] = self.id
attributes.each do |var|
value = instance_variable_get "@#{var}"
hsh[var.to_sym] = value
end
hsh
end
def counter
self.class.instance_variable_get('@store').counter
end
def store
self.class.instance_variable_get('@store')
end
def attributes
self.class.instance_variable_get('@attributes')
end
end
class DataModel
include DataModelBasic
attr_accessor :id
def initialize(values = {})
values.map do |key, _|
self.public_send("#{key}=", values[key]) if self.respond_to? "#{key}="
end
end
class << self
def attributes(*attributes)
@attributes = attributes
attributes.each do |value|
attr_accessor(value)
self.define_singleton_method("find_by_#{value}") do |arg|
query = {value => arg}
@store.find(query)
end
end
end
def data_store(store = {})
@store = store unless @store
@store
end
def where(hsh)
@store.find(hsh).map do |value|
self.new(value)
end.to_a
end
end
end
module Store
attr_accessor :counter
def create(hash)
@storage[hash[:id]] = hash
end
def find(hash)
end
def update(id, hash)
@storage[id] = hash
end
def delete(hash)
@storage[hash[:id]] = nil
end
end
class HashStore
include Store
def initialize
@storage = {}
@counter = 0
end
def find(hash)
result = []
@storage.select do |_, elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value
end
end
result
end
end
class ArrayStore
include Store
def initialize
@storage = []
@counter = 0
end
def find(hash)
result = []
@storage.each do |elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value && !(result.include? elem)
end
end
result
end
end
class DeleteUnsavedRecordError < StandardError
end

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

.F.F....F.F.FF/tmp/d20161202-15620-1ikgm72/spec.rb:164: warning: toplevel constant DeleteUnsavedRecordError referenced by DataModel::DeleteUnsavedRecordError
.....F....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-1ikgm72/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 has #find_by_<attribute> methods
     Failure/Error: expect(user_model.find_by_first_name('Ivan').map(&:id)).to eq [record.id]
     NoMethodError:
       undefined method `id' for {:id=>1, :first_name=>"Ivan", :last_name=>"Ivanov", :age=>nil}:Hash
     # /tmp/d20161202-15620-1ikgm72/spec.rb:43:in `map'
     # /tmp/d20161202-15620-1ikgm72/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)>'

  3) DataModel equality comparison uses #equal? if there are no ids
     Failure/Error: expect(first_user).to_not eq second_user
       
       expected: value != #<#<Class:0x007fa2d3e2ee38>:0x007fa2d3e2de98 @first_name="Ivan">
            got: #<#<Class:0x007fa2d3e2ee38>:0x007fa2d3e2e0f0 @first_name="Ivan">
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -#<#<Class:0x007fa2d3e2ee38>:0x007fa2d3e2de98 @first_name="Ivan">
       +#<#<Class:0x007fa2d3e2ee38>:0x007fa2d3e2e0f0 @first_name="Ivan">
     # /tmp/d20161202-15620-1ikgm72/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)>'

  4) DataModel.where finds records by multiple attributes
     Failure/Error: expect(records).to eq ['Ivanov']
       
       expected: ["Ivanov"]
            got: ["Ivanov", "Ivanov", "Petrov"]
       
       (compared using ==)
     # /tmp/d20161202-15620-1ikgm72/spec.rb:135: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.where raises an error if the query is by an unknown key
     Failure/Error: DataModel::UnknownAttributeError,
     NameError:
       uninitialized constant DataModel::UnknownAttributeError
     # /tmp/d20161202-15620-1ikgm72/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)>'

  6) DataModel#delete deletes only the record for which it is called
     Failure/Error: expect(all_records).to match_array ['Petar', 'Georgi']
       expected collection contained:  ["Georgi", "Petar"]
       actual collection contained:    []
       the missing elements were:      ["Georgi", "Petar"]
     # /tmp/d20161202-15620-1ikgm72/spec.rb:159: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) 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: []
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -[{:id=>3, :name=>"Gosho"}]
       +[]
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-1ikgm72/spec.rb:235
     # /tmp/d20161202-15620-1ikgm72/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)>'

  8) ArrayStore behaves like a data store #delete can delete multiple records with a single query
     Failure/Error: store.delete(name: 'Pesho')
     TypeError:
       no implicit conversion from nil to integer
     Shared Example Group: "a data store" called from /tmp/d20161202-15620-1ikgm72/spec.rb:239
     # /tmp/d20161202-15620-1ikgm72/solution.rb:94:in `[]='
     # /tmp/d20161202-15620-1ikgm72/solution.rb:94:in `delete'
     # /tmp/d20161202-15620-1ikgm72/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.02768 seconds
25 examples, 8 failures

Failed examples:

rspec /tmp/d20161202-15620-1ikgm72/spec.rb:21 # DataModel has attributes and data_model getters
rspec /tmp/d20161202-15620-1ikgm72/spec.rb:39 # DataModel has #find_by_<attribute> methods
rspec /tmp/d20161202-15620-1ikgm72/spec.rb:108 # DataModel equality comparison uses #equal? if there are no ids
rspec /tmp/d20161202-15620-1ikgm72/spec.rb:129 # DataModel.where finds records by multiple attributes
rspec /tmp/d20161202-15620-1ikgm72/spec.rb:142 # DataModel.where raises an error if the query is by an unknown key
rspec /tmp/d20161202-15620-1ikgm72/spec.rb:151 # DataModel#delete deletes only the record for which it is called
rspec /tmp/d20161202-15620-1ikgm72/spec.rb:218 # HashStore behaves like a data store #delete can delete multiple records with a single query
rspec /tmp/d20161202-15620-1ikgm72/spec.rb:218 # ArrayStore behaves like a data store #delete can delete multiple records with a single query

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

Калина обнови решението на 29.11.2016 22:39 (преди около 8 години)

+module DataModelBasic
+ def attributes
+ self.instance_variables.map do |var|

Това е добра идея, тъй като в инстанцията на теория можеш да имаш други инстанционни променливи, а този код искаш да върне само атрибутите.

Помисли дали няма вариант да запазиш/вземеш списъка с атрибути директно отнякъде.

+ str = var.to_s.gsub /^@/, ''
+ str.to_sym if respond_to? "#{str}="
+ end
+ end
+
+ def save
+ self.class.instance_variable_get('@store').create(convert(self))
+ self
+ end
+
+ def delete
+ raise DeleteUnsavedRecordError unless id
+ self.class.instance_variable_get('@store').delete(convert(self))
+ self
+ end
+
+ def ==(other_object)
+ return false if self.class != other_object.class
+ return true if self.id == other_object.id
+ self.object_id == other_object.object_id
+ end
+end
+
+class DataModel
+ include DataModelBasic
+ attr_accessor :id
+
+ def initialize(values = {})
+ values.map do |key, _|
+ self.public_send("#{key}=", values[key]) if self.respond_to? "#{key}="
+ end
+ end
+
+ class << self
+ def attributes(*attributes)
+ attributes.each do |value|
+ attr_accessor(value)
+ self.define_singleton_method("find_by_#{value}") do |arg|
+ query = {}
+ query[value] = arg
+ instance_variable_get('@store').find(query)
+ end
+ end
+ end
+
+ def data_store(store = {})
+ instance_variable_set('@store', store) unless instance_variable_get('@store')
+ instance_variable_get('@store')
+ end
+
+ def where(hsh)
+ instance_variable_get('@store').find(hsh).map do |value|
+ self.new(value)
+ end.to_a
+ end
+
+ def method_missing(_, _)
+ raise NoMethodError
+ end
+ end
+
+ private
+ def convert(object)
+ hsh = {}
+ object.class.instance_variable_get('@store').counter = counter + 1 unless id
+ hsh[:id] = counter
+ object.instance_variables.each do |var|
+ str = var.to_s.gsub /^@/, ''
+ hsh[str.to_sym] = instance_variable_get var if respond_to? "#{str}="
+ end
+ object.id = counter
+ hsh
+ end
+
+ def counter
+ self.class.instance_variable_get('@store').counter
+ end
+end
+
+module Store
+ attr_accessor :counter
+
+ def create(hash)
+ @storage[hash[:id]] = hash
+ end
+
+ def find(hash)
+ end
+
+ def update(id, hash)
+ @storage[id] = hash
+ end
+
+ def delete(hash)
+ @storage[hash[:id]] = nil
+ end
+end
+
+class HashStore
+ include Store
+
+ def initialize
+ @storage = {}
+ @counter = 0
+ end
+
+ def find(hash)
+ result = []
+ @storage.select do |_, elem|
+ hash.each do |key, value|
+ result << elem if elem && elem[key] == value
+ end
+ end
+ result
+ end
+end
+
+class ArrayStore
+ include Store
+
+ def initialize
+ @storage = []
+ @counter = 0
+ end
+
+ def find(hash)
+ result = []
+ @storage.each do |elem|
+ hash.each do |key, value|
+ result << elem if elem && elem[key] == value && !(result.include? elem)
+ end
+ end
+ result
+ end
+end
+
+class DeleteUnsavedRecordError < StandardError
+end

Калина обнови решението на 30.11.2016 00:12 (преди около 8 години)

module DataModelBasic
def attributes
- self.instance_variables.map do |var|
- str = var.to_s.gsub /^@/, ''
- str.to_sym if respond_to? "#{str}="
- end
+ self.class.instance_variable_get('@attributes')
end
def save
+ self.class.instance_variable_get('@store').counter = counter + 1 unless @id
+ @id = self.class.instance_variable_get('@store').counter unless @id
self.class.instance_variable_get('@store').create(convert(self))
self
end
def delete
raise DeleteUnsavedRecordError unless id
self.class.instance_variable_get('@store').delete(convert(self))
self
end
def ==(other_object)
return false if self.class != other_object.class
return true if self.id == other_object.id
self.object_id == other_object.object_id
end
end
class DataModel
include DataModelBasic
attr_accessor :id
def initialize(values = {})
values.map do |key, _|
self.public_send("#{key}=", values[key]) if self.respond_to? "#{key}="
end
end
class << self
def attributes(*attributes)
+ @attributes = []
attributes.each do |value|
+ @attributes << value
attr_accessor(value)
self.define_singleton_method("find_by_#{value}") do |arg|
- query = {}
- query[value] = arg
- instance_variable_get('@store').find(query)
+ query = {value => arg}
+ @store.find(query)
end
end
end
def data_store(store = {})
- instance_variable_set('@store', store) unless instance_variable_get('@store')
- instance_variable_get('@store')
+ @store = store unless @store
+ @store
end
def where(hsh)
- instance_variable_get('@store').find(hsh).map do |value|
+ @store.find(hsh).map do |value|
self.new(value)
end.to_a
end
def method_missing(_, _)
raise NoMethodError
end
end
private
def convert(object)
hsh = {}
- object.class.instance_variable_get('@store').counter = counter + 1 unless id
- hsh[:id] = counter
- object.instance_variables.each do |var|
- str = var.to_s.gsub /^@/, ''
- hsh[str.to_sym] = instance_variable_get var if respond_to? "#{str}="
+ hsh[:id] = object.id
+ object.class.instance_variable_get('@attributes').each do |var|
+ value = instance_variable_get "@#{var}"
+ hsh[var.to_sym] = value if value
end
- object.id = counter
hsh
end
def counter
self.class.instance_variable_get('@store').counter
end
end
module Store
attr_accessor :counter
def create(hash)
@storage[hash[:id]] = hash
end
def find(hash)
end
def update(id, hash)
@storage[id] = hash
end
def delete(hash)
+ p hash
@storage[hash[:id]] = nil
end
end
class HashStore
include Store
def initialize
@storage = {}
@counter = 0
end
def find(hash)
result = []
@storage.select do |_, elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value
end
end
result
end
end
class ArrayStore
include Store
def initialize
@storage = []
@counter = 0
end
def find(hash)
result = []
@storage.each do |elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value && !(result.include? elem)
end
end
result
end
end
class DeleteUnsavedRecordError < StandardError
end

Калина обнови решението на 30.11.2016 06:22 (преди около 8 години)

module DataModelBasic
- def attributes
- self.class.instance_variable_get('@attributes')
- end
-
def save
- self.class.instance_variable_get('@store').counter = counter + 1 unless @id
- @id = self.class.instance_variable_get('@store').counter unless @id
- self.class.instance_variable_get('@store').create(convert(self))
+ store.create(self.convert)
self
end
def delete
raise DeleteUnsavedRecordError unless id
- self.class.instance_variable_get('@store').delete(convert(self))
+ store.delete(self.convert)
self
end
def ==(other_object)
return false if self.class != other_object.class
return true if self.id == other_object.id
self.object_id == other_object.object_id
end
+
+ def convert
+ hsh = {}
+ store.counter = counter + 1 unless @id
+ @id = counter unless @id
+ hsh[:id] = self.id
+ attributes.each do |var|
+ value = instance_variable_get "@#{var}"
+ hsh[var.to_sym] = value if value
+ end
+ hsh
+ end
+
+ def counter
+ self.class.instance_variable_get('@store').counter
+ end
+
+ def store
+ self.class.instance_variable_get('@store')
+ end
+
+ def attributes
+ self.class.instance_variable_get('@attributes')
+ end
end
class DataModel
include DataModelBasic
attr_accessor :id
def initialize(values = {})
values.map do |key, _|
self.public_send("#{key}=", values[key]) if self.respond_to? "#{key}="
end
end
class << self
def attributes(*attributes)
@attributes = []
attributes.each do |value|
@attributes << value
attr_accessor(value)
self.define_singleton_method("find_by_#{value}") do |arg|
query = {value => arg}
@store.find(query)
end
end
end
def data_store(store = {})
@store = store unless @store
@store
end
def where(hsh)
@store.find(hsh).map do |value|
self.new(value)
end.to_a
end
-
- def method_missing(_, _)
- raise NoMethodError
- end
end
-
- private
- def convert(object)
- hsh = {}
- hsh[:id] = object.id
- object.class.instance_variable_get('@attributes').each do |var|
- value = instance_variable_get "@#{var}"
- hsh[var.to_sym] = value if value
- end
- hsh
- end
-
- def counter
- self.class.instance_variable_get('@store').counter
- end
end
module Store
attr_accessor :counter
def create(hash)
@storage[hash[:id]] = hash
end
def find(hash)
end
def update(id, hash)
@storage[id] = hash
end
def delete(hash)
p hash
@storage[hash[:id]] = nil
end
end
class HashStore
include Store
def initialize
@storage = {}
@counter = 0
end
def find(hash)
result = []
@storage.select do |_, elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value
end
end
result
end
end
class ArrayStore
include Store
def initialize
@storage = []
@counter = 0
end
def find(hash)
result = []
@storage.each do |elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value && !(result.include? elem)
end
end
result
end
end
class DeleteUnsavedRecordError < StandardError
end

Калина обнови решението на 30.11.2016 06:30 (преди около 8 години)

module DataModelBasic
def save
store.create(self.convert)
self
end
def delete
raise DeleteUnsavedRecordError unless id
store.delete(self.convert)
self
end
def ==(other_object)
return false if self.class != other_object.class
return true if self.id == other_object.id
self.object_id == other_object.object_id
end
def convert
hsh = {}
store.counter = counter + 1 unless @id
@id = counter unless @id
hsh[:id] = self.id
attributes.each do |var|
value = instance_variable_get "@#{var}"
hsh[var.to_sym] = value if value
end
hsh
end
def counter
self.class.instance_variable_get('@store').counter
end
def store
self.class.instance_variable_get('@store')
end
def attributes
self.class.instance_variable_get('@attributes')
end
end
class DataModel
include DataModelBasic
attr_accessor :id
def initialize(values = {})
values.map do |key, _|
self.public_send("#{key}=", values[key]) if self.respond_to? "#{key}="
end
end
class << self
def attributes(*attributes)
- @attributes = []
+ @attributes = attributes
attributes.each do |value|
- @attributes << value
attr_accessor(value)
self.define_singleton_method("find_by_#{value}") do |arg|
query = {value => arg}
@store.find(query)
end
end
end
def data_store(store = {})
@store = store unless @store
@store
end
def where(hsh)
@store.find(hsh).map do |value|
self.new(value)
end.to_a
end
end
end
module Store
attr_accessor :counter
def create(hash)
@storage[hash[:id]] = hash
end
def find(hash)
end
def update(id, hash)
@storage[id] = hash
end
def delete(hash)
p hash
@storage[hash[:id]] = nil
end
end
class HashStore
include Store
def initialize
@storage = {}
@counter = 0
end
def find(hash)
result = []
@storage.select do |_, elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value
end
end
result
end
end
class ArrayStore
include Store
def initialize
@storage = []
@counter = 0
end
def find(hash)
result = []
@storage.each do |elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value && !(result.include? elem)
end
end
result
end
end
class DeleteUnsavedRecordError < StandardError
end

Калина обнови решението на 30.11.2016 20:47 (преди около 8 години)

module DataModelBasic
def save
store.create(self.convert)
self
end
def delete
raise DeleteUnsavedRecordError unless id
store.delete(self.convert)
self
end
def ==(other_object)
return false if self.class != other_object.class
return true if self.id == other_object.id
self.object_id == other_object.object_id
end
def convert
hsh = {}
store.counter = counter + 1 unless @id
@id = counter unless @id
hsh[:id] = self.id
attributes.each do |var|
value = instance_variable_get "@#{var}"
- hsh[var.to_sym] = value if value
+ hsh[var.to_sym] = value
end
hsh
end
def counter
self.class.instance_variable_get('@store').counter
end
def store
self.class.instance_variable_get('@store')
end
def attributes
self.class.instance_variable_get('@attributes')
end
end
class DataModel
include DataModelBasic
attr_accessor :id
def initialize(values = {})
values.map do |key, _|
self.public_send("#{key}=", values[key]) if self.respond_to? "#{key}="
end
end
class << self
def attributes(*attributes)
@attributes = attributes
attributes.each do |value|
attr_accessor(value)
self.define_singleton_method("find_by_#{value}") do |arg|
query = {value => arg}
@store.find(query)
end
end
end
def data_store(store = {})
@store = store unless @store
@store
end
def where(hsh)
@store.find(hsh).map do |value|
self.new(value)
end.to_a
end
end
end
module Store
attr_accessor :counter
def create(hash)
@storage[hash[:id]] = hash
end
def find(hash)
end
def update(id, hash)
@storage[id] = hash
end
def delete(hash)
- p hash
@storage[hash[:id]] = nil
end
end
class HashStore
include Store
def initialize
@storage = {}
@counter = 0
end
def find(hash)
result = []
@storage.select do |_, elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value
end
end
result
end
end
class ArrayStore
include Store
def initialize
@storage = []
@counter = 0
end
def find(hash)
result = []
@storage.each do |elem|
hash.each do |key, value|
result << elem if elem && elem[key] == value && !(result.include? elem)
end
end
result
end
end
class DeleteUnsavedRecordError < StandardError
end