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.
Files changed (70) hide show
  1. checksums.yaml +15 -0
  2. data/.ruby-version +1 -0
  3. data/.travis.yml +7 -4
  4. data/Appraisals +9 -0
  5. data/Guardfile +7 -1
  6. data/README.md +5 -1
  7. data/Rakefile +12 -0
  8. data/gemfiles/rails_3.gemfile +8 -0
  9. data/gemfiles/rails_3.gemfile.lock +109 -0
  10. data/gemfiles/rails_4.gemfile +8 -0
  11. data/gemfiles/rails_4.gemfile.lock +117 -0
  12. data/lib/memory_model/base/actions/class_methods.rb +27 -0
  13. data/lib/memory_model/base/actions.rb +75 -0
  14. data/lib/memory_model/base/attributes.rb +87 -0
  15. data/lib/memory_model/base/auto_increment.rb +47 -0
  16. data/lib/memory_model/base/collectible.rb +26 -0
  17. data/lib/memory_model/base/conversion.rb +11 -0
  18. data/lib/memory_model/base/fields/field.rb +57 -0
  19. data/lib/memory_model/base/fields/field_set.rb +87 -0
  20. data/lib/memory_model/base/fields.rb +49 -0
  21. data/lib/memory_model/base/operations/comparisons.rb +25 -0
  22. data/lib/memory_model/base/operations.rb +10 -0
  23. data/lib/memory_model/base/persistence.rb +13 -11
  24. data/lib/memory_model/base.rb +58 -43
  25. data/lib/memory_model/collection/finders.rb +75 -0
  26. data/lib/memory_model/collection/index/multi.rb +61 -0
  27. data/lib/memory_model/collection/index/unique.rb +79 -0
  28. data/lib/memory_model/collection/index.rb +86 -0
  29. data/lib/memory_model/collection/initializers.rb +48 -0
  30. data/lib/memory_model/collection/loader_delegate.rb +63 -0
  31. data/lib/memory_model/collection/marshaled_record.rb +23 -0
  32. data/lib/memory_model/collection/operations.rb +82 -0
  33. data/lib/memory_model/collection.rb +18 -73
  34. data/lib/memory_model/version.rb +1 -1
  35. data/lib/memory_model.rb +7 -7
  36. data/memory_model.gemspec +8 -3
  37. data/spec/benchmark/benchmark.rb +126 -0
  38. data/spec/memory_model/base/{actionable_spec.rb → actions_spec.rb} +34 -103
  39. data/spec/memory_model/base/{attributable_spec.rb → attributes_spec.rb} +4 -6
  40. data/spec/memory_model/base/{collectable_spec.rb → collectible_spec.rb} +1 -1
  41. data/spec/memory_model/base/fieldable/field_set_spec.rb +23 -37
  42. data/spec/memory_model/base/fieldable/field_spec.rb +16 -16
  43. data/spec/memory_model/base/{fieldable_spec.rb → fields_spec.rb} +1 -1
  44. data/spec/memory_model/base/{comparable_spec.rb → operations/comparisons_spec.rb} +4 -4
  45. data/spec/memory_model/base/persistence_spec.rb +2 -2
  46. data/spec/memory_model/base_spec.rb +10 -9
  47. data/spec/memory_model/collection_spec.rb +24 -146
  48. data/spec/spec_helper.rb +11 -0
  49. data/spec/support/delegate_matcher.rb +40 -0
  50. metadata +120 -65
  51. data/.idea/.rakeTasks +0 -7
  52. data/.idea/dictionaries/jwaldrip.xml +0 -3
  53. data/.idea/encodings.xml +0 -5
  54. data/.idea/memory_model.iml +0 -47
  55. data/.idea/misc.xml +0 -8
  56. data/.idea/modules.xml +0 -9
  57. data/.idea/scopes/scope_settings.xml +0 -5
  58. data/.idea/vcs.xml +0 -7
  59. data/.idea/workspace.xml +0 -701
  60. data/lib/memory_model/base/actionable.rb +0 -95
  61. data/lib/memory_model/base/attributable.rb +0 -76
  62. data/lib/memory_model/base/collectable.rb +0 -22
  63. data/lib/memory_model/base/comparable.rb +0 -16
  64. data/lib/memory_model/base/fieldable/field.rb +0 -35
  65. data/lib/memory_model/base/fieldable/field_set.rb +0 -74
  66. data/lib/memory_model/base/fieldable.rb +0 -45
  67. data/lib/memory_model/base/versionable.rb +0 -17
  68. data/lib/memory_model/core_ext/object.rb +0 -5
  69. data/spec/memory_model/base/versionable_spec.rb +0 -31
  70. 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,5 +0,0 @@
1
- class Object
2
- def not_a?(klass)
3
- !is_a?(klass)
4
- end
5
- end
@@ -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
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Object do
4
-
5
- describe '#not_a?' do
6
- it 'should be in the inverse of #is_a?' do
7
- object = Hash.new
8
- object.not_a?(Hash).should_not == object.is_a?(Hash)
9
- end
10
- end
11
-
12
- end