superstore 2.4.4 → 2.5.0

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