superstore 2.4.4 → 2.5.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 (95) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +4 -6
  3. data/Gemfile +2 -3
  4. data/{Gemfile-rails4.2 → Gemfile.rails6} +2 -3
  5. data/README.md +4 -34
  6. data/lib/superstore.rb +17 -18
  7. data/lib/superstore/adapters/abstract_adapter.rb +1 -27
  8. data/lib/superstore/adapters/jsonb_adapter.rb +4 -132
  9. data/lib/superstore/associations.rb +6 -1
  10. data/lib/superstore/associations/association.rb +6 -0
  11. data/lib/superstore/associations/association_scope.rb +20 -0
  12. data/lib/superstore/associations/belongs_to.rb +3 -1
  13. data/lib/superstore/associations/has_many.rb +15 -2
  14. data/lib/superstore/associations/reflection.rb +8 -2
  15. data/lib/superstore/attribute_assignment.rb +7 -0
  16. data/lib/superstore/attribute_methods.rb +1 -109
  17. data/lib/superstore/attribute_methods/primary_key.rb +20 -11
  18. data/lib/superstore/attributes.rb +13 -0
  19. data/lib/superstore/base.rb +8 -33
  20. data/lib/superstore/core.rb +7 -65
  21. data/lib/superstore/model_schema.rb +35 -0
  22. data/lib/superstore/persistence.rb +31 -115
  23. data/lib/superstore/railtie.rb +3 -11
  24. data/lib/superstore/relation/scrolling.rb +48 -0
  25. data/lib/superstore/timestamp.rb +13 -0
  26. data/lib/superstore/types.rb +11 -9
  27. data/lib/superstore/types/array_type.rb +3 -7
  28. data/lib/superstore/types/boolean_type.rb +7 -12
  29. data/lib/superstore/types/date_range_type.rb +7 -0
  30. data/lib/superstore/types/date_type.rb +7 -10
  31. data/lib/superstore/types/float_type.rb +3 -11
  32. data/lib/superstore/types/geo_point_type.rb +30 -0
  33. data/lib/superstore/types/integer_range_type.rb +19 -0
  34. data/lib/superstore/types/integer_type.rb +8 -14
  35. data/lib/superstore/types/json_type.rb +1 -1
  36. data/lib/superstore/types/range_type.rb +51 -0
  37. data/lib/superstore/types/string_type.rb +4 -4
  38. data/lib/superstore/types/time_type.rb +10 -8
  39. data/superstore.gemspec +4 -3
  40. data/test/support/jsonb.rb +3 -1
  41. data/test/support/models.rb +8 -5
  42. data/test/test_helper.rb +6 -2
  43. data/test/unit/adapters/adapter_test.rb +1 -3
  44. data/test/unit/associations/belongs_to_test.rb +1 -1
  45. data/test/unit/associations/has_many_test.rb +10 -2
  46. data/test/unit/attribute_methods/dirty_test.rb +8 -19
  47. data/test/unit/attribute_methods/primary_key_test.rb +1 -1
  48. data/test/unit/attribute_methods_test.rb +10 -22
  49. data/test/unit/{attribute_methods/typecasting_test.rb → attributes_test.rb} +13 -39
  50. data/test/unit/base_test.rb +4 -0
  51. data/test/unit/caching_test.rb +1 -1
  52. data/test/unit/callbacks_test.rb +4 -4
  53. data/test/unit/core_test.rb +9 -19
  54. data/test/unit/persistence_test.rb +17 -54
  55. data/test/unit/{scope/batches_test.rb → relation/scrolling_test.rb} +9 -5
  56. data/test/unit/serialization_test.rb +10 -2
  57. data/test/unit/{timestamps_test.rb → timestamp_test.rb} +5 -5
  58. data/test/unit/types/array_type_test.rb +3 -18
  59. data/test/unit/types/boolean_type_test.rb +7 -21
  60. data/test/unit/types/date_range_type_test.rb +28 -0
  61. data/test/unit/types/date_type_test.rb +15 -6
  62. data/test/unit/types/float_type_test.rb +4 -19
  63. data/test/unit/types/geo_point_type_test.rb +24 -0
  64. data/test/unit/types/integer_range_type_test.rb +28 -0
  65. data/test/unit/types/integer_type_test.rb +7 -16
  66. data/test/unit/types/string_type_test.rb +9 -13
  67. data/test/unit/types/time_type_test.rb +17 -11
  68. data/test/unit/validations_test.rb +2 -2
  69. metadata +39 -39
  70. data/lib/superstore/attribute_methods/definition.rb +0 -17
  71. data/lib/superstore/attribute_methods/dirty.rb +0 -52
  72. data/lib/superstore/attribute_methods/typecasting.rb +0 -53
  73. data/lib/superstore/caching.rb +0 -13
  74. data/lib/superstore/callbacks.rb +0 -29
  75. data/lib/superstore/connection.rb +0 -24
  76. data/lib/superstore/errors.rb +0 -10
  77. data/lib/superstore/inspect.rb +0 -25
  78. data/lib/superstore/model.rb +0 -38
  79. data/lib/superstore/schema.rb +0 -20
  80. data/lib/superstore/scope.rb +0 -73
  81. data/lib/superstore/scope/batches.rb +0 -27
  82. data/lib/superstore/scope/finder_methods.rb +0 -51
  83. data/lib/superstore/scope/query_methods.rb +0 -52
  84. data/lib/superstore/scoping.rb +0 -30
  85. data/lib/superstore/timestamps.rb +0 -19
  86. data/lib/superstore/type.rb +0 -16
  87. data/lib/superstore/types/base_type.rb +0 -23
  88. data/lib/superstore/validations.rb +0 -44
  89. data/test/unit/attribute_methods/definition_test.rb +0 -16
  90. data/test/unit/inspect_test.rb +0 -26
  91. data/test/unit/schema_test.rb +0 -15
  92. data/test/unit/scope/finder_methods_test.rb +0 -62
  93. data/test/unit/scope/query_methods_test.rb +0 -37
  94. data/test/unit/scoping_test.rb +0 -7
  95. data/test/unit/types/base_type_test.rb +0 -11
@@ -0,0 +1,20 @@
1
+ module Superstore
2
+ module Associations
3
+ class AssociationScope < ActiveRecord::Relation
4
+ def initialize(klass, association)
5
+ super(klass)
6
+ @association = association
7
+ end
8
+
9
+ def exec_queries
10
+ super.each { |r| @association.set_inverse_instance r }
11
+ end
12
+
13
+ def <<(*records)
14
+ if loaded?
15
+ @records = @records + records
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -17,6 +17,8 @@ module Superstore
17
17
  end
18
18
  end
19
19
 
20
+ def belongs_to?; true; end
21
+
20
22
  private
21
23
 
22
24
  def get_record
@@ -32,4 +34,4 @@ module Superstore
32
34
 
33
35
  end
34
36
  end
35
- end
37
+ end
@@ -19,12 +19,25 @@ module Superstore
19
19
  self.target = relation
20
20
  end
21
21
 
22
+ def set_inverse_instance(record)
23
+ return unless reflection.inverse_name
24
+
25
+ inverse = record.association(reflection.inverse_name)
26
+ inverse.target = owner
27
+ end
28
+
22
29
  private
23
30
 
31
+ def inverse_of
32
+ return unless reflection.inverse_name
33
+
34
+ @inverse_of ||= association_class.reflect_on_association reflection.inverse_name
35
+ end
36
+
24
37
  def load_collection
25
- association_class.where(reflection.foreign_key => owner.try(reflection.primary_key))
38
+ AssociationScope.new(association_class, self).where("document ->> '#{reflection.foreign_key}' = '#{owner.try(reflection.primary_key)}'")
26
39
  end
27
40
 
28
41
  end
29
42
  end
30
- end
43
+ end
@@ -18,7 +18,7 @@ module Superstore
18
18
  when :has_one
19
19
  Superstore::Associations::HasOne
20
20
  end
21
-
21
+
22
22
  end
23
23
 
24
24
  def instance_variable_name
@@ -45,12 +45,18 @@ module Superstore
45
45
  options[:polymorphic]
46
46
  end
47
47
 
48
+ def belongs_to?; false; end
49
+
48
50
  def class_name
49
51
  @class_name ||= (options[:class_name] || name.to_s.classify)
50
52
  end
51
53
 
54
+ def inverse_name
55
+ options[:inverse_of]
56
+ end
57
+
52
58
  private
53
-
59
+
54
60
  def derive_foreign_key
55
61
  case macro
56
62
  when :has_many, :has_one
@@ -0,0 +1,7 @@
1
+ module Superstore
2
+ module AttributeAssignment
3
+ def _assign_attribute(k, v)
4
+ public_send("#{k}=", v) if respond_to?("#{k}=")
5
+ end
6
+ end
7
+ end
@@ -1,117 +1,9 @@
1
1
  module Superstore
2
2
  module AttributeMethods
3
3
  extend ActiveSupport::Concern
4
- include ActiveModel::AttributeMethods
5
4
 
6
5
  included do
7
- attribute_method_suffix("=")
8
-
9
- # (Alias for the protected read_attribute method).
10
- def [](attr_name)
11
- read_attribute(attr_name)
12
- end
13
-
14
- # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
15
- # (Alias for the protected write_attribute method).
16
- def []=(attr_name, value)
17
- write_attribute(attr_name, value)
18
- end
19
- end
20
-
21
- module ClassMethods
22
- def inherited(child_class)
23
- child_class.define_attribute_methods
24
- super
25
- end
26
-
27
- def define_attribute_methods
28
- return if attribute_methods_generated?
29
- super(attribute_definitions.keys)
30
- @attribute_methods_generated = true
31
- end
32
-
33
- def attribute_methods_generated?
34
- @attribute_methods_generated ||= false
35
- end
36
-
37
- def dangerous_attribute_method?(name)
38
- false
39
- end
40
-
41
- def has_attribute?(attr_name)
42
- attribute_definitions.key?(attr_name.to_s)
43
- end
44
- end
45
-
46
- def write_attribute(name, value)
47
- @attributes[name.to_s] = self.class.typecast_attribute(name, value)
48
- end
49
-
50
- def read_attribute(name)
51
- name = name.to_s unless name.is_a?(String)
52
-
53
- if name == self.class.primary_key
54
- send(name)
55
- else
56
- @attributes[name]
57
- end
58
- end
59
- alias_method :_read_attribute, :read_attribute
60
-
61
- def attribute_present?(attribute)
62
- value = _read_attribute(attribute)
63
- !value.nil? && !(value.respond_to?(:empty?) && value.empty?)
6
+ include PrimaryKey
64
7
  end
65
-
66
- def has_attribute?(name)
67
- @attributes.key?(name.to_s)
68
- end
69
- alias_method :attribute_exists?, :has_attribute?
70
-
71
- def attributes
72
- results = {}
73
- @attributes.each_key do |key|
74
- results[key] = read_attribute(key)
75
- end
76
- results
77
- end
78
-
79
- def attributes=(attributes)
80
- attributes.each do |(name, value)|
81
- send("#{name}=", value)
82
- end
83
- end
84
-
85
- def method_missing(method_id, *args, &block)
86
- self.class.define_attribute_methods unless self.class.attribute_methods_generated?
87
-
88
- match = if ActiveRecord.version >= Gem::Version.new('5.0')
89
- # Active Record 5.0
90
- matched_attribute_method(method_id.to_s)
91
- else
92
- # Active Record 4.2
93
- match_attribute_method?(method_id.to_s)
94
- end
95
- match ? attribute_missing(match, *args, &block) : super
96
- end
97
-
98
- def respond_to?(*args)
99
- self.class.define_attribute_methods unless self.class.attribute_methods_generated?
100
- super
101
- end
102
-
103
- protected
104
- def attribute_method?(name)
105
- !!attribute_definitions[name.to_s]
106
- end
107
-
108
- private
109
- def attribute(name)
110
- read_attribute(name)
111
- end
112
-
113
- def attribute=(name, value)
114
- write_attribute(name, value)
115
- end
116
8
  end
117
9
  end
@@ -1,25 +1,34 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Superstore
2
4
  module AttributeMethods
3
5
  module PrimaryKey
4
6
  extend ActiveSupport::Concern
5
7
 
8
+ included do
9
+ attribute :id, type: :string
10
+ include AttributeOverrides
11
+ end
12
+
6
13
  module ClassMethods
7
- PRIMARY_KEY = 'id'
8
14
  def primary_key
9
- PRIMARY_KEY
15
+ 'id'
10
16
  end
11
17
  end
12
18
 
13
- def id
14
- @id ||= self.class._generate_key(self)
15
- end
16
-
17
- def id=(id)
18
- @id = id
19
- end
19
+ module AttributeOverrides
20
+ def id
21
+ value = super
22
+ if value.nil?
23
+ value = self.class._generate_key(self)
24
+ @attributes.write_from_user(self.class.primary_key, value)
25
+ end
26
+ value
27
+ end
20
28
 
21
- def attributes
22
- super.update(self.class.primary_key => id)
29
+ def attributes
30
+ super.update(self.class.primary_key => id)
31
+ end
23
32
  end
24
33
  end
25
34
  end
@@ -0,0 +1,13 @@
1
+ module Superstore
2
+ module Attributes
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def attribute(name, options)
7
+ type_name = "superstore_#{options.fetch(:type)}".to_sym
8
+
9
+ super(name, type_name)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,44 +1,19 @@
1
- require 'set'
2
-
3
1
  require 'superstore/types'
4
2
 
5
3
  module Superstore
6
- class Base
7
-
8
- extend ActiveModel::Naming
9
- include ActiveModel::Conversion
10
- extend ActiveSupport::DescendantsTracker
11
- include ActiveModel::Serializers::JSON
12
- include GlobalID::Identification
13
-
14
- extend ActiveRecord::Delegation::DelegateCache
15
- extend ActiveRecord::ConnectionHandling
16
- include ActiveRecord::Persistence
17
- include ActiveRecord::ModelSchema
18
- include ActiveRecord::Inheritance
19
- include ActiveRecord::Attributes
20
- include ActiveRecord::Associations
21
- include ActiveRecord::AutosaveAssociation
22
- include ActiveRecord::Reflection
4
+ class Base < ActiveRecord::Base
23
5
 
24
- include Model
6
+ self.connection_specification_name = 'primary'
7
+ self.abstract_class = true
25
8
  include Core
26
- include Connection
27
- include Identity
28
- include Inspect
29
9
  include Persistence
10
+ include ModelSchema
11
+ include AttributeAssignment
12
+ include Attributes
30
13
  include AttributeMethods
31
- include Validations
32
- include AttributeMethods::Dirty
33
- include AttributeMethods::PrimaryKey
34
- include AttributeMethods::Typecasting
14
+ include Timestamp
35
15
  include Associations
36
- include Callbacks
37
- include Timestamps
38
- include Scoping
39
- include Caching
40
16
 
17
+ include Identity
41
18
  end
42
19
  end
43
-
44
- ActiveSupport.run_load_hooks(:superstore, Superstore::Base)
@@ -2,76 +2,18 @@ module Superstore
2
2
  module Core
3
3
  extend ActiveSupport::Concern
4
4
 
5
- module ClassMethods
6
- def inspect
7
- if self == Base
8
- super
9
- else
10
- attr_list = attribute_definitions.keys * ', '
11
- "#{super}(#{attr_list.truncate(140 * 1.7337)})"
12
- end
13
- end
5
+ def inspect
6
+ inspection = ["#{self.class.primary_key}: #{id.inspect}"]
14
7
 
15
- def initialize_generated_modules # :nodoc:
16
- generated_association_methods
17
- end
8
+ (self.class.attribute_names - [self.class.primary_key]).each do |name|
9
+ value = send(name)
18
10
 
19
- def generated_association_methods
20
- @generated_association_methods ||= begin
21
- mod = const_set(:GeneratedAssociationMethods, Module.new)
22
- include mod
23
- mod
11
+ if value.present? || value === false
12
+ inspection << "#{name}: #{attribute_for_inspect(name)}"
24
13
  end
25
14
  end
26
15
 
27
- def arel_table # :nodoc:
28
- @arel_table ||= Arel::Table.new(table_name, self)
29
- end
30
-
31
- def subclass_from_attributes?(attrs)
32
- false
33
- end
34
- end
35
-
36
- def initialize(attributes=nil)
37
- @new_record = true
38
- @destroyed = false
39
- @association_cache = {}
40
-
41
- @attributes = {}
42
- self.attributes = attributes || {}
43
-
44
- yield self if block_given?
45
- end
46
-
47
- def initialize_dup(other)
48
- @attributes = other.attributes
49
- @attributes['created_at'] = nil
50
- @attributes['updated_at'] = nil
51
- @attributes.delete(self.class.primary_key)
52
- @id = nil
53
- @new_record = true
54
- @destroyed = false
55
- @association_cache = {}
56
- super
57
- end
58
-
59
- def to_param
60
- id
61
- end
62
-
63
- def hash
64
- id.hash
65
- end
66
-
67
- def ==(comparison_object)
68
- comparison_object.equal?(self) ||
69
- (comparison_object.instance_of?(self.class) &&
70
- comparison_object.id == id)
71
- end
72
-
73
- def eql?(comparison_object)
74
- self == (comparison_object)
16
+ "#<#{self.class} #{inspection * ', '}>"
75
17
  end
76
18
  end
77
19
  end
@@ -0,0 +1,35 @@
1
+ module Superstore
2
+ module ModelSchema
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :superstore_column, default: 'document'
7
+ end
8
+
9
+ module ClassMethods
10
+ def attributes_builder # :nodoc:
11
+ @attributes_builder ||= ActiveModel::AttributeSet::Builder.new(attribute_types, _default_attributes)
12
+ end
13
+
14
+ def load_schema! # :nodoc:
15
+ @columns_hash = {}
16
+
17
+ attributes_to_define_after_schema_loads.each do |name, (type, options)|
18
+ if type.is_a?(Symbol)
19
+ type = ActiveRecord::Type.lookup(type, **options.except(:default))
20
+ end
21
+
22
+ define_attribute(name, type, **options.slice(:default))
23
+ end
24
+ end
25
+
26
+ def attribute_names
27
+ attribute_types.keys
28
+ end
29
+
30
+ def column_names
31
+ attribute_names
32
+ end
33
+ end
34
+ end
35
+ end