Калина обнови решението на 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)
instance_variable_get
от къде взима инстанционната променлива? Трябва ли ти тук?
+ 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