memory_model 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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