testingrecord 0.7 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 163d454cbedadbfb903dcfd141aafe10554fb9aa6b8ef2ff8c5c44abe6d1a7b3
4
- data.tar.gz: bb4fcd7db84017b1032cbf1a362cdddc9fae583b7b71146c6b4019ed7b372288
3
+ metadata.gz: fd979c6e6979b672916851b0be5603d6a4dabbc43855b596c5272fbd93dfdadc
4
+ data.tar.gz: 9ff521bdd86bff0ed97c43f055b5add594296376dca665005271a320e44518d3
5
5
  SHA512:
6
- metadata.gz: 1cb9024a7d5dd9cda0f15841e955ae45e4caa508d90c13433be6e70fc12aa75b7ec54cd9f9e1bb04b050e4f7e23408558106a18e67cd64403a20da57184e4057
7
- data.tar.gz: 0d479648df51da1455edfa5b2b5c4a749cefc6f68e572fd3e9384a8d21b7e097a5a5e3d4a5ae2a049b8338815b07c4a389defbbdb9e0b710bdfbd3fe64c30fa7
6
+ metadata.gz: f922ea85183b6c28646ac42a9325d509d85c12bf3d447056defd626b01760b16b0d049749bc02ccc50be4fa7036e59be5973f16a7649400d1fd978398df04d0b
7
+ data.tar.gz: 87ceaea89ae230ecf0d760cfda87bf5de91953ea6584fd364986dc770b90369725680b8a63404d147262bbaccc8a9fd252941a6803ebef1efe024fcef1248b12
@@ -36,6 +36,21 @@ module TestingRecord
36
36
  find_by({ id: })&.first&.tap { |entity| entity.class.current = entity }
37
37
  end
38
38
 
39
+ # Checks to see whether an entity exists with the provided primary_key
40
+ #
41
+ # @return [Boolean]
42
+ def with_primary_key?(primary_key)
43
+ !with_primary_key(primary_key).nil?
44
+ end
45
+
46
+ # Finds an entity with the provided primary_key
47
+ # If one is found, set it as the current entity
48
+ #
49
+ # @return [TestingRecord::Model, nil]
50
+ def with_primary_key(primary_key)
51
+ find_by({ __primary_key => primary_key })&.first&.tap { |entity| entity.class.current = entity }
52
+ end
53
+
39
54
  private
40
55
 
41
56
  # Finds all entities that match specified attribute values
@@ -10,13 +10,21 @@ module TestingRecord
10
10
  module Settings
11
11
  include DSL::Validation::Input
12
12
 
13
- attr_reader :__primary_key
13
+ def __primary_key
14
+ if instance_variable_defined?(:@__primary_key)
15
+ @__primary_key
16
+ elsif superclass.respond_to?(:__primary_key)
17
+ superclass.__primary_key
18
+ else
19
+ TestingRecord.default_primary_key
20
+ end
21
+ end
14
22
 
15
23
  # Create a cache of the entities, named according to the classname
16
24
  #
17
25
  # @return [Symbol]
18
26
  def caching(option)
19
- raise Error, 'Invalid caching option, must be :enabled or :disabled' unless caching_valid?(option)
27
+ raise Error::InvalidConfigurationError, 'Invalid caching option, must be :enabled or :disabled' unless caching_valid?(option)
20
28
  return unless option == :enabled
21
29
 
22
30
  instance_variable_set(:@all, [])
@@ -28,7 +36,9 @@ module TestingRecord
28
36
  #
29
37
  # @return [Symbol]
30
38
  def primary_key(option)
31
- instance_variable_set(:@__primary_key, option.to_sym)
39
+ raise Error::InvalidConfigurationError, 'Invalid primary key value, must be a Symbol' unless option.is_a?(Symbol)
40
+
41
+ instance_variable_set(:@__primary_key, option)
32
42
  end
33
43
  end
34
44
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TestingRecord
4
+ module Error
5
+ class AttributeError < StandardError; end
6
+ class EntityError < StandardError; end
7
+ class InvalidConfigurationError < StandardError; end
8
+ end
9
+ end
@@ -14,33 +14,74 @@ module TestingRecord
14
14
  attr_reader :attributes
15
15
 
16
16
  class << self
17
- attr_accessor :current
17
+ attr_reader :current
18
18
 
19
19
  # Creates an instance of the model
20
- # -> Creating iVar values for each attribute that was provided
21
- # -> Adding it to the cache if caching is enabled
20
+ # -> Ensures that the primary key is specified in the attribute payload
21
+ # -> Validates that a duplicate entity has not been made (If caching is enabled)
22
+ # -> Creates iVar values (Symbol format) and attr_reader's for each attribute that was provided
23
+ # -> Adds helper methods (If the model has been configured to include helpers)
24
+ # -> Adds it to the cache (If caching is enabled)
22
25
  #
23
26
  # @return [TestingRecord::Model]
24
27
  def create(attributes)
25
- new(attributes).tap do |entity|
26
- configure_data(entity, attributes)
27
- add_helpers(attributes) if entity.class.instance_variable_get(:@include_helpers)
28
- cache_entity(entity)
28
+ if respond_to?(:all)
29
+ create_with_caching(attributes)
30
+ else
31
+ create_without_caching(attributes)
29
32
  end
30
33
  end
31
34
 
35
+ # Sets the current entity instance to the one supplied (Or removes it if supplied `nil`)
36
+ #
37
+ # @return [TestingRecord::Model, nil]
38
+ def current=(entity)
39
+ if entity
40
+ TestingRecord.logger.info("Switching current user from #{@current} to #{entity}")
41
+ else
42
+ TestingRecord.logger.info("Purging current user: #{@current}")
43
+ end
44
+ @current = entity
45
+ end
46
+
32
47
  # Deletes the instance of the model from the cache (Does nothing if caching is disabled)
33
48
  #
34
- # @return [TestingRecord::Model]
49
+ # @return [TestingRecord::Model, nil]
35
50
  def delete(entity)
36
- all.delete(entity) if respond_to?(:all)
51
+ return unless respond_to?(:all)
52
+
53
+ self.current = nil if entity == current
54
+ all.delete(entity)
55
+ end
56
+
57
+ # Deletes the instance of the model from the cache (Does nothing if caching is disabled)
58
+ #
59
+ # @return [TestingRecord::Model, nil]
60
+ def delete_by_id(id)
61
+ delete(with_id(id)) if respond_to?(:all)
37
62
  end
38
63
 
39
64
  private
40
65
 
41
- def cache_entity(entity)
42
- return unless respond_to?(:all)
66
+ def create_with_caching(attributes)
67
+ ensure_primary_key_presence(attributes)
68
+ ensure_deduplication(attributes)
69
+ new(attributes.transform_keys(&:to_sym)).tap do |entity|
70
+ configure_data(entity, attributes)
71
+ add_helpers(attributes) if entity.class.instance_variable_get(:@include_helpers)
72
+ cache_entity(entity)
73
+ end
74
+ end
75
+
76
+ def create_without_caching(attributes)
77
+ ensure_primary_key_presence(attributes)
78
+ new(attributes.transform_keys(&:to_sym)).tap do |entity|
79
+ configure_data(entity, attributes)
80
+ add_helpers(attributes) if entity.class.instance_variable_get(:@include_helpers)
81
+ end
82
+ end
43
83
 
84
+ def cache_entity(entity)
44
85
  self.current = entity
45
86
  all << entity
46
87
  TestingRecord.logger.debug("Entity: #{entity} added to cache")
@@ -52,6 +93,20 @@ module TestingRecord
52
93
  entity.class.attr_reader attribute_key
53
94
  end
54
95
  end
96
+
97
+ def ensure_deduplication(attributes)
98
+ pk_value = attributes[__primary_key]
99
+ return unless with_primary_key?(pk_value)
100
+
101
+ TestingRecord.logger.error("#{name} entity already exists with primary key: #{pk_value}")
102
+ raise Error::EntityError, "#{name} entity already exists with primary key: #{pk_value}"
103
+ end
104
+
105
+ def ensure_primary_key_presence(attributes)
106
+ return if attributes.key?(__primary_key)
107
+
108
+ raise Error::AttributeError, "#{name} entity has not been supplied with the primary key: #{__primary_key}"
109
+ end
55
110
  end
56
111
 
57
112
  def initialize(attributes = {})
@@ -74,15 +129,15 @@ module TestingRecord
74
129
  end
75
130
 
76
131
  # Updates an entity (instance), of a model
77
- # -> Updating iVar values for each attribute that was provided
132
+ # -> Updating iVar values for each attribute that was provided (Converting to symbolized format)
78
133
  # -> It will **not** create new reader methods for new variables added
79
134
  #
80
135
  # @return [TestingRecord::Model]
81
136
  def update(attrs)
82
- attrs.each do |key, value|
137
+ attrs.transform_keys(&:to_sym).each do |key, value|
83
138
  attributes[key] = value
84
139
  instance_variable_set("@#{key}", value)
85
- TestingRecord.logger.info("Updated '#{key}' on current #{self.class} entity to be '#{value}'")
140
+ TestingRecord.logger.info("Updated '#{key}' on the #{self.class} entity to be '#{value}'")
86
141
  end
87
142
  self
88
143
  end
@@ -90,7 +145,6 @@ module TestingRecord
90
145
  private
91
146
 
92
147
  def reorder_attributes_for_inspect!
93
- return unless self.class.__primary_key
94
148
  return if attributes.keys.first == self.class.__primary_key
95
149
 
96
150
  pk_value = attributes.delete(self.class.__primary_key)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TestingRecord
4
- VERSION = '0.7'
4
+ VERSION = '1.0'
5
5
  end
@@ -1,16 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'testing_record/dsl'
4
+ require_relative 'testing_record/error'
4
5
  require_relative 'testing_record/logger'
5
6
  require_relative 'testing_record/model'
6
7
  require_relative 'testing_record/version'
7
8
 
8
9
  # {TestingRecord} namespace
9
10
  module TestingRecord
10
- # Generic TestingRecord error. Will be extended in the future
11
- class Error < StandardError; end
12
-
13
11
  class << self
12
+ attr_reader :default_primary_key
13
+
14
+ def configure
15
+ yield self
16
+ end
17
+
18
+ # Configure a default primary key for all TestingRecord models
19
+ def default_primary_key=(value)
20
+ raise InvalidConfigurationError, 'Invalid primary key value, must be a Symbol' unless value.is_a?(Symbol)
21
+
22
+ @default_primary_key = value
23
+ TestingRecord::Model.primary_key value
24
+ end
25
+
26
+ # Specify the default primary key to `:id` (This is procedural so will be overwritten at runtime if config defined)
27
+ TestingRecord.default_primary_key = :id
28
+
14
29
  # The Testing Record logger object - This is called automatically in several
15
30
  # locations and will log messages according to the normal Ruby protocol
16
31
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: testingrecord
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.7'
4
+ version: '1.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luke Hill
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-03 00:00:00.000000000 Z
11
+ date: 2026-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: automation_helpers
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '5'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '7'
22
+ version: '8'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '5'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '7'
32
+ version: '8'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: logger
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -64,28 +64,28 @@ dependencies:
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: 1.85.0
67
+ version: 1.86.0
68
68
  type: :development
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 1.85.0
74
+ version: 1.86.0
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: rubocop-performance
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: 1.25.0
81
+ version: 1.26.1
82
82
  type: :development
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: 1.25.0
88
+ version: 1.26.1
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: rubocop-rspec
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +119,7 @@ files:
119
119
  - lib/testing_record/dsl/builder/settings.rb
120
120
  - lib/testing_record/dsl/validation.rb
121
121
  - lib/testing_record/dsl/validation/input.rb
122
+ - lib/testing_record/error.rb
122
123
  - lib/testing_record/logger.rb
123
124
  - lib/testing_record/model.rb
124
125
  - lib/testing_record/version.rb