memory_model 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -4
- data/Appraisals +9 -0
- data/Guardfile +7 -1
- data/README.md +5 -1
- data/Rakefile +12 -0
- data/gemfiles/rails_3.gemfile +8 -0
- data/gemfiles/rails_3.gemfile.lock +109 -0
- data/gemfiles/rails_4.gemfile +8 -0
- data/gemfiles/rails_4.gemfile.lock +117 -0
- data/lib/memory_model/base/actions/class_methods.rb +27 -0
- data/lib/memory_model/base/actions.rb +75 -0
- data/lib/memory_model/base/attributes.rb +87 -0
- data/lib/memory_model/base/auto_increment.rb +47 -0
- data/lib/memory_model/base/collectible.rb +26 -0
- data/lib/memory_model/base/conversion.rb +11 -0
- data/lib/memory_model/base/fields/field.rb +57 -0
- data/lib/memory_model/base/fields/field_set.rb +87 -0
- data/lib/memory_model/base/fields.rb +49 -0
- data/lib/memory_model/base/operations/comparisons.rb +25 -0
- data/lib/memory_model/base/operations.rb +10 -0
- data/lib/memory_model/base/persistence.rb +13 -11
- data/lib/memory_model/base.rb +58 -43
- data/lib/memory_model/collection/finders.rb +75 -0
- data/lib/memory_model/collection/index/multi.rb +61 -0
- data/lib/memory_model/collection/index/unique.rb +79 -0
- data/lib/memory_model/collection/index.rb +86 -0
- data/lib/memory_model/collection/initializers.rb +48 -0
- data/lib/memory_model/collection/loader_delegate.rb +63 -0
- data/lib/memory_model/collection/marshaled_record.rb +23 -0
- data/lib/memory_model/collection/operations.rb +82 -0
- data/lib/memory_model/collection.rb +18 -73
- data/lib/memory_model/version.rb +1 -1
- data/lib/memory_model.rb +7 -7
- data/memory_model.gemspec +8 -3
- data/spec/benchmark/benchmark.rb +126 -0
- data/spec/memory_model/base/{actionable_spec.rb → actions_spec.rb} +34 -103
- data/spec/memory_model/base/{attributable_spec.rb → attributes_spec.rb} +4 -6
- data/spec/memory_model/base/{collectable_spec.rb → collectible_spec.rb} +1 -1
- data/spec/memory_model/base/fieldable/field_set_spec.rb +23 -37
- data/spec/memory_model/base/fieldable/field_spec.rb +16 -16
- data/spec/memory_model/base/{fieldable_spec.rb → fields_spec.rb} +1 -1
- data/spec/memory_model/base/{comparable_spec.rb → operations/comparisons_spec.rb} +4 -4
- data/spec/memory_model/base/persistence_spec.rb +2 -2
- data/spec/memory_model/base_spec.rb +10 -9
- data/spec/memory_model/collection_spec.rb +24 -146
- data/spec/spec_helper.rb +11 -0
- data/spec/support/delegate_matcher.rb +40 -0
- metadata +120 -65
- data/.idea/.rakeTasks +0 -7
- data/.idea/dictionaries/jwaldrip.xml +0 -3
- data/.idea/encodings.xml +0 -5
- data/.idea/memory_model.iml +0 -47
- data/.idea/misc.xml +0 -8
- data/.idea/modules.xml +0 -9
- data/.idea/scopes/scope_settings.xml +0 -5
- data/.idea/vcs.xml +0 -7
- data/.idea/workspace.xml +0 -701
- data/lib/memory_model/base/actionable.rb +0 -95
- data/lib/memory_model/base/attributable.rb +0 -76
- data/lib/memory_model/base/collectable.rb +0 -22
- data/lib/memory_model/base/comparable.rb +0 -16
- data/lib/memory_model/base/fieldable/field.rb +0 -35
- data/lib/memory_model/base/fieldable/field_set.rb +0 -74
- data/lib/memory_model/base/fieldable.rb +0 -45
- data/lib/memory_model/base/versionable.rb +0 -17
- data/lib/memory_model/core_ext/object.rb +0 -5
- data/spec/memory_model/base/versionable_spec.rb +0 -31
- data/spec/memory_model/core_ext/object_spec.rb +0 -12
@@ -1,95 +0,0 @@
|
|
1
|
-
require 'ice_nine'
|
2
|
-
require 'ice_nine/core_ext/object'
|
3
|
-
|
4
|
-
module MemoryModel::Base::Actionable
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
define_model_callbacks :create, :update, :save, :destroy
|
9
|
-
attr_reader :timestamp
|
10
|
-
end
|
11
|
-
|
12
|
-
VALID_IVARS = [
|
13
|
-
:@deleted,
|
14
|
-
:@attributes,
|
15
|
-
:@timestamp,
|
16
|
-
:@version
|
17
|
-
]
|
18
|
-
|
19
|
-
def commit
|
20
|
-
@timestamp = Time.now
|
21
|
-
@version = SecureRandom.hex(6)
|
22
|
-
self.class.insert self
|
23
|
-
self
|
24
|
-
end
|
25
|
-
|
26
|
-
def delete
|
27
|
-
@deleted = true
|
28
|
-
commit
|
29
|
-
freeze
|
30
|
-
end
|
31
|
-
|
32
|
-
def deleted?
|
33
|
-
!!@deleted
|
34
|
-
end
|
35
|
-
|
36
|
-
def deleted_at
|
37
|
-
deleted? ? @timestamp : nil
|
38
|
-
end
|
39
|
-
|
40
|
-
def destroy
|
41
|
-
run_callbacks :destroy do
|
42
|
-
delete
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def dup
|
47
|
-
deep_dup
|
48
|
-
end
|
49
|
-
|
50
|
-
def deep_dup
|
51
|
-
Marshal.load Marshal.dump self
|
52
|
-
end
|
53
|
-
|
54
|
-
def freeze
|
55
|
-
instance_variables.reject { |ivar| ivar.in? VALID_IVARS }.each do |ivar|
|
56
|
-
remove_instance_variable ivar if instance_variable_defined?(ivar)
|
57
|
-
end
|
58
|
-
instance_variables.each { |ivar| instance_variable_get(ivar).freeze }
|
59
|
-
deep_freeze
|
60
|
-
super
|
61
|
-
end
|
62
|
-
|
63
|
-
def save
|
64
|
-
callback = persisted? ? :update : :create
|
65
|
-
run_callbacks callback do
|
66
|
-
run_callbacks :save do
|
67
|
-
commit
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def restore
|
73
|
-
instance = frozen? ? self.dup : self
|
74
|
-
instance.instance_variable_set :@deleted, false
|
75
|
-
instance.save
|
76
|
-
instance
|
77
|
-
end
|
78
|
-
|
79
|
-
module ClassMethods
|
80
|
-
|
81
|
-
def create(attributes={})
|
82
|
-
new(attributes).save
|
83
|
-
end
|
84
|
-
|
85
|
-
def delete_all
|
86
|
-
all.map(&:delete).reject(&:deleted?).empty?
|
87
|
-
end
|
88
|
-
|
89
|
-
def destroy_all
|
90
|
-
all.map(&:destroy).reject(&:deleted?).empty?
|
91
|
-
end
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
module MemoryModel::Base::Attributable
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
include ActiveModel::AttributeMethods
|
4
|
-
include ActiveModel::Dirty
|
5
|
-
|
6
|
-
included do
|
7
|
-
attr_reader :attributes
|
8
|
-
delegate :to_hash, to: :attributes
|
9
|
-
attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!'
|
10
|
-
attribute_method_prefix 'clear_'
|
11
|
-
end
|
12
|
-
|
13
|
-
def has_attribute?(key)
|
14
|
-
case value = @attributes[key]
|
15
|
-
when NilClass, String
|
16
|
-
!value.nil?
|
17
|
-
else
|
18
|
-
value.present?
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def inspect
|
23
|
-
inspection = if @attributes
|
24
|
-
fields.reduce([]) { |array, name|
|
25
|
-
array << "#{name}: #{attribute_for_inspect(name)}" if has_attribute?(name)
|
26
|
-
array
|
27
|
-
}.join(", ")
|
28
|
-
else
|
29
|
-
"not initialized"
|
30
|
-
end
|
31
|
-
"#<#{[self.class, inspection].join(' ')}>"
|
32
|
-
end
|
33
|
-
|
34
|
-
def read_attribute(name)
|
35
|
-
@attributes[name]
|
36
|
-
end
|
37
|
-
|
38
|
-
alias :[] :read_attribute
|
39
|
-
|
40
|
-
def write_attribute(name, value)
|
41
|
-
raise MemoryModel::InvalidFieldError,
|
42
|
-
"#{name} is not a valid field" unless fields.include? name
|
43
|
-
raise MemoryModel::FieldReadOnlyError,
|
44
|
-
"#{name} is read only" if fields[name].options[:readonly]
|
45
|
-
|
46
|
-
send "#{name}_will_change!" unless value == read_attribute(name) || new_record?
|
47
|
-
@attributes[name] = value
|
48
|
-
end
|
49
|
-
|
50
|
-
alias :[]= :write_attribute
|
51
|
-
|
52
|
-
protected
|
53
|
-
|
54
|
-
def attribute_for_inspect(attr_name)
|
55
|
-
value = read_attribute(attr_name)
|
56
|
-
|
57
|
-
if value.is_a?(String) && value.length > 50
|
58
|
-
"#{value[0..50]}...".inspect
|
59
|
-
elsif value.is_a?(Date) || value.is_a?(Time)
|
60
|
-
value.to_s
|
61
|
-
else
|
62
|
-
value.inspect
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def reset_attribute_to_default!(attr)
|
69
|
-
write_attribute attr, fields.default_values(self).with_indifferent_access[attr]
|
70
|
-
end
|
71
|
-
|
72
|
-
def clear_attribute(attr)
|
73
|
-
write_attribute attr, nil
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
|
-
module MemoryModel::Base::Collectable
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
extend ConcernedInheritance
|
6
|
-
|
7
|
-
inherited do
|
8
|
-
instance_variable_set :@collection, baseclass.collection
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
delegate :all, :find, :insert, :<<, :deleted, to: :collection
|
13
|
-
delegate :first, :last, to: :all
|
14
|
-
|
15
|
-
def collection
|
16
|
-
return nil if self == MemoryModel::Base
|
17
|
-
@collection ||= MemoryModel::Collection.new(self)
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module MemoryModel::Base::Comparable
|
2
|
-
|
3
|
-
def ==(other_object)
|
4
|
-
attributes.slice(*fields.comparable) ==
|
5
|
-
other_object.to_hash.with_indifferent_access.slice(*fields.comparable)
|
6
|
-
end
|
7
|
-
|
8
|
-
def !=(other_object)
|
9
|
-
!(self == other_object)
|
10
|
-
end
|
11
|
-
|
12
|
-
def ===(other_object)
|
13
|
-
other_object.kind_of?(self.class) && self == other_object
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
class MemoryModel::Base::Fieldable::Field
|
2
|
-
|
3
|
-
attr_reader :name, :options
|
4
|
-
delegate :inspect, to: :to_sym
|
5
|
-
|
6
|
-
def initialize(name, options={ })
|
7
|
-
@name = name.to_sym
|
8
|
-
@options = options.reverse_merge!({ readonly: false, comparable: true })
|
9
|
-
end
|
10
|
-
|
11
|
-
def ==(other_object)
|
12
|
-
self.to_sym == other_object.to_sym
|
13
|
-
end
|
14
|
-
|
15
|
-
def comparable?
|
16
|
-
!!@options[:comparable]
|
17
|
-
end
|
18
|
-
|
19
|
-
def default
|
20
|
-
@options[:default]
|
21
|
-
end
|
22
|
-
|
23
|
-
def readonly?
|
24
|
-
!!@options[:readonly]
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_sym
|
28
|
-
@name.to_sym
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_s
|
32
|
-
@name.to_s
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/hash/keys'
|
2
|
-
require 'set'
|
3
|
-
|
4
|
-
class MemoryModel::Base::Fieldable::FieldSet
|
5
|
-
|
6
|
-
Field = MemoryModel::Base::Fieldable::Field
|
7
|
-
|
8
|
-
attr_reader :fields
|
9
|
-
delegate :include?, to: :fields
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@fields = []
|
13
|
-
end
|
14
|
-
|
15
|
-
def [](name)
|
16
|
-
@fields.find { |f| f.name == name.to_sym }
|
17
|
-
end
|
18
|
-
|
19
|
-
def <<(attr)
|
20
|
-
attr = Field.new(attr) unless attr.is_a? Field
|
21
|
-
@fields << attr
|
22
|
-
end
|
23
|
-
|
24
|
-
def add(attr, options={ })
|
25
|
-
@fields.delete_if { |f| f == attr }
|
26
|
-
@fields << Field.new(attr, options)
|
27
|
-
end
|
28
|
-
|
29
|
-
def comparable
|
30
|
-
@fields.select(&:comparable?).map(&:to_sym)
|
31
|
-
end
|
32
|
-
|
33
|
-
def inspect
|
34
|
-
to_a.inspect
|
35
|
-
end
|
36
|
-
|
37
|
-
def default_values(model, attributes={ })
|
38
|
-
@fields.reduce(attributes.symbolize_keys) do |attrs, field|
|
39
|
-
raise MemoryModel::ReadonlyFieldError if attrs[field.name].present? && field.readonly?
|
40
|
-
default = field.default.is_a?(Symbol) ? field.default.to_proc : field.default
|
41
|
-
attrs[field.name] ||= if default.nil?
|
42
|
-
nil
|
43
|
-
elsif default.is_a? String
|
44
|
-
default
|
45
|
-
elsif default.not_a?(::Proc)
|
46
|
-
raise ArgumentError, "#{default} must be a string, symbol, lamba or proc"
|
47
|
-
elsif default.lambda? && default.arity == 0
|
48
|
-
default.call
|
49
|
-
elsif default.arity.in? -1..0
|
50
|
-
model.instance_eval(&default)
|
51
|
-
elsif default.arity == 1
|
52
|
-
default.yield model
|
53
|
-
else
|
54
|
-
raise ArgumentError, "#{default} must have an arity of 0..1, got #{default.arity}"
|
55
|
-
end
|
56
|
-
attrs
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def to_a
|
61
|
-
@fields.map(&:to_sym)
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def method_missing(m, *args, &block)
|
67
|
-
if to_a.respond_to? m
|
68
|
-
to_a.send m, *args, &block
|
69
|
-
else
|
70
|
-
super
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
require 'active_support/dependencies/autoload'
|
3
|
-
require 'securerandom'
|
4
|
-
|
5
|
-
module MemoryModel::Base::Fieldable
|
6
|
-
extend ConcernedInheritance
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
extend ActiveSupport::Autoload
|
9
|
-
include ActiveModel::AttributeMethods
|
10
|
-
|
11
|
-
autoload :FieldSet
|
12
|
-
autoload :Field
|
13
|
-
|
14
|
-
inherited do
|
15
|
-
instance_variable_set :@fields, baseclass.fields
|
16
|
-
field :id, readonly: true, default: -> { SecureRandom.uuid }, comparable: false
|
17
|
-
end
|
18
|
-
|
19
|
-
module ClassMethods
|
20
|
-
def field(attr, options={ })
|
21
|
-
define_attribute_method attr unless instance_method_already_implemented? attr
|
22
|
-
fields.add(attr.to_sym, options)
|
23
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
24
|
-
def #{attr}
|
25
|
-
read_attribute :#{attr}
|
26
|
-
end
|
27
|
-
|
28
|
-
def #{attr}=(value)
|
29
|
-
write_attribute :#{attr}, value
|
30
|
-
end
|
31
|
-
RUBY
|
32
|
-
end
|
33
|
-
|
34
|
-
def fields
|
35
|
-
return nil if self == MemoryModel::Base
|
36
|
-
@fields ||= FieldSet.new
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
def fields
|
42
|
-
self.class.fields
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module MemoryModel::Base::Versionable
|
2
|
-
|
3
|
-
def versions
|
4
|
-
instances = self.class.collection.records.select { |i| i.id == self.id }
|
5
|
-
instances.reduce({ }) do |hash, instance|
|
6
|
-
hash[instance.version] = instance
|
7
|
-
hash
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def version
|
12
|
-
@version
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
# MemoryModel::Base::Immutable # todo!
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MemoryModel::Base::Versionable do
|
4
|
-
|
5
|
-
let(:model) do
|
6
|
-
Class.new(MemoryModel::Base)
|
7
|
-
end
|
8
|
-
let(:instance) do
|
9
|
-
model.new
|
10
|
-
end
|
11
|
-
before(:each) do
|
12
|
-
stub_const('MyModel', model)
|
13
|
-
end
|
14
|
-
|
15
|
-
describe '#versions' do
|
16
|
-
it 'should have a number of versions' do
|
17
|
-
10.times.each do |index|
|
18
|
-
instance.versions.size.should == index
|
19
|
-
instance.commit
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe '#version' do
|
25
|
-
it 'should be the latest version' do
|
26
|
-
3.times.each { instance.commit }
|
27
|
-
instance.version.should == instance.versions.keys.last
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|