sdn_test_simple_car_repository 0.2.1 → 0.2.2

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: 4021d729ce417b6ba742100c32e43c24eee66bfdec345765739a8c9525ac21ae
4
- data.tar.gz: d2d6b40b45f659e5ea688a12029fd155fabea3efe157b8e584c82e17bbc42bf3
3
+ metadata.gz: bac9e4f15496700b39ee469b8f9d355df3cebc6c843582b84c633cad3565a55b
4
+ data.tar.gz: 52527ecd6eed3edbf59e03cbafd5f1cab28cfff5d410de841c50cf9c3594e373
5
5
  SHA512:
6
- metadata.gz: b5592af1e3ace226346df4c3b26bd5b207dd8b771b9454d5023c1f870a118d2601cf44a5d09c7b7e1d759172da84fe347fc03559012bf8f23113573307825652
7
- data.tar.gz: df63c67dddc510a35f6f29b503a34d225e557992a5291a6ecca63750be5d4a7e37114f0a5dbddb4106cf469a0923a70562f39686a2e6e5bb068033996b9126b5
6
+ metadata.gz: 1ee39ffc8afb3683c9a788c907a4db72ea1593d84d88821759672af761197ce2a90e49d0f4c12008bf23ca181aafb99bf84a0cb9bcdb817722f8e7f7f37b844c
7
+ data.tar.gz: d524e07a88a20428c12090328d47a4cc1223de8b8da17838b9db5fe2aa2783d74d3b4a621e5ee6e7852011062fe474d80a89c07c1dcb4fbbd9a3f0d4ceb3b084
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,8 +1,8 @@
1
- AllCops:
2
- TargetRubyVersion: 3.1
3
-
4
- Style/StringLiterals:
5
- EnforcedStyle: double_quotes
6
-
7
- Style/StringLiteralsInInterpolation:
8
- EnforcedStyle: double_quotes
1
+ AllCops:
2
+ TargetRubyVersion: 3.1
3
+
4
+ Style/StringLiterals:
5
+ EnforcedStyle: double_quotes
6
+
7
+ Style/StringLiteralsInInterpolation:
8
+ EnforcedStyle: double_quotes
data/LICENSE.txt CHANGED
@@ -1,21 +1,21 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2026 Graftcode
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Graftcode
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,12 +1,12 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- require "rubocop/rake_task"
9
-
10
- RuboCop::RakeTask.new
11
-
12
- task default: %i[spec rubocop]
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -1,30 +1,30 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/grft_test_simple_car_repository/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "sdn_test_simple_car_repository"
7
- spec.version = GrftTestSimpleCarRepository::VERSION
8
- spec.authors = ["GraftCode"]
9
- spec.email = ["info@graftcode.com"]
10
-
11
- spec.summary = "Simple car in-memory repository"
12
- spec.description = "Provides an in-memory repository for SimpleCar objects with add/get/update/delete operations and sample seed data."
13
- spec.homepage = "https://graftcode.com"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = ">= 3.1.0"
16
-
17
- spec.metadata["homepage_uri"] = spec.homepage
18
-
19
- gemspec = File.basename(__FILE__)
20
- spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
21
- ls.readlines("\x0", chomp: true).reject do |f|
22
- f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
23
- end
24
- end
25
- spec.bindir = "exe"
26
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
- spec.require_paths = ["lib"]
28
-
29
- spec.add_dependency "sdn_test_simple_car", ">= 0.2.1"
30
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/grft_test_simple_car_repository/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "sdn_test_simple_car_repository"
7
+ spec.version = GrftTestSimpleCarRepository::VERSION
8
+ spec.authors = ["GraftCode"]
9
+ spec.email = ["info@graftcode.com"]
10
+
11
+ spec.summary = "Simple car in-memory repository"
12
+ spec.description = "Provides an in-memory repository for SimpleCar objects with add/get/update/delete operations and sample seed data."
13
+ spec.homepage = "https://graftcode.com"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 3.1.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+
19
+ gemspec = File.basename(__FILE__)
20
+ spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
21
+ ls.readlines("\x0", chomp: true).reject do |f|
22
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
23
+ end
24
+ end
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_dependency "sdn_test_simple_car", ">= 0.2.1"
30
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrftTestSimpleCarRepository
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
@@ -1,118 +1,193 @@
1
- # frozen_string_literal: true
2
-
3
- require "grft_test_simple_car"
4
-
5
- # An in-memory repository that stores SimpleCar instances keyed by string ID.
6
- class InMemorySimpleCarRepository
7
- # ── static members ──────────────────────────────────────────────
8
-
9
- DEFAULT_CAPACITY = 100
10
-
11
- @total_instances_created = 0
12
-
13
- class << self
14
- attr_accessor :total_instances_created
15
- end
16
-
17
- def self.create_with_sample_data
18
- new
19
- end
20
-
21
- # ── constructor ─────────────────────────────────────────────────
22
-
23
- def initialize
24
- self.class.instance_variable_set(:@total_instances_created, self.class.total_instances_created + 1)
25
- @store = {}
26
-
27
- samples = [
28
- SimpleCar.new("Toyota", "Corolla", 2018, "0"),
29
- SimpleCar.new("Tesla", "Model 3", 2021, "1"),
30
- SimpleCar.new("Ford", "Mustang", 1967, "2"),
31
- SimpleCar.new("Honda", "Civic", 2015, "3"),
32
- SimpleCar.new("Chevrolet", "Camaro", 2020, "4")
33
- ]
34
-
35
- samples.each { |car| add(car) }
36
- end
37
-
38
- # ── CRUD ────────────────────────────────────────────────────────
39
-
40
- def add(car)
41
- raise ArgumentError, "car cannot be nil" if car.nil?
42
- raise ArgumentError, "SimpleCar with Id #{car.id} already exists." if @store.key?(car.id)
43
-
44
- @store[car.id] = car
45
- end
46
-
47
- def add_range(cars)
48
- raise ArgumentError, "cars cannot be nil" if cars.nil?
49
-
50
- cars.each { |car| add(car) }
51
- end
52
-
53
- def get(id)
54
- raise ArgumentError, "id cannot be nil or whitespace" if id.nil? || id.strip.empty?
55
-
56
- @store[id]
57
- end
58
-
59
- def get_all
60
- @store.values
61
- end
62
-
63
- def update(car)
64
- raise ArgumentError, "car cannot be nil" if car.nil?
65
-
66
- return false unless @store.key?(car.id)
67
-
68
- @store[car.id] = car
69
- true
70
- end
71
-
72
- def delete(id)
73
- raise ArgumentError, "id cannot be nil or whitespace" if id.nil? || id.strip.empty?
74
-
75
- return false unless @store.key?(id)
76
-
77
- @store.delete(id)
78
- true
79
- end
80
-
81
- # ── queries returning complex types ─────────────────────────────
82
-
83
- def find_by_make(make)
84
- raise ArgumentError, "make cannot be nil or whitespace" if make.nil? || make.strip.empty?
85
-
86
- lower_make = make.downcase
87
- @store.values.select { |c| c.make.downcase == lower_make }
88
- end
89
-
90
- def find_by_year_range(min_year, max_year)
91
- @store.values.select { |c| c.year >= min_year && c.year <= max_year }
92
- end
93
-
94
- # ── queries returning primitive arrays ──────────────────────────
95
-
96
- def get_years
97
- @store.values.map(&:year).uniq.sort
98
- end
99
-
100
- def get_makes
101
- @store.values.map(&:make).uniq.sort
102
- end
103
-
104
- # ── bulk operations with primitive-array input ──────────────────
105
-
106
- def delete_by_ids(ids)
107
- raise ArgumentError, "ids cannot be nil" if ids.nil?
108
-
109
- count = 0
110
- ids.each do |id|
111
- if @store.key?(id)
112
- @store.delete(id)
113
- count += 1
114
- end
115
- end
116
- count
117
- end
118
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "grft_test_simple_car"
4
+
5
+ # An in-memory, thread-safe repository that stores SimpleCar instances using a string identifier.
6
+ #
7
+ # The repository pre-loads five sample cars on construction so that graft smoke tests can issue
8
+ # queries immediately without seeding data.
9
+ class InMemorySimpleCarRepository
10
+ # ── static members ──────────────────────────────────────────
11
+
12
+ # Default capacity hint for the repository.
13
+ DEFAULT_CAPACITY = 100
14
+
15
+ @total_instances_created = 0
16
+
17
+ class << self
18
+ # @return [Integer] Total number of repository instances created so far.
19
+ attr_accessor :total_instances_created
20
+ end
21
+
22
+ # Returns a new repository pre-loaded with sample data.
23
+ #
24
+ # @return [InMemorySimpleCarRepository] Repository containing the default sample cars used across graft tests.
25
+ # @example
26
+ # repo = InMemorySimpleCarRepository.create_with_sample_data
27
+ # repo.get_all.size #=> 5
28
+ def self.create_with_sample_data
29
+ new
30
+ end
31
+
32
+ # ── constructor ─────────────────────────────────────────────
33
+
34
+ # Initializes the repository and seeds it with five sample cars.
35
+ #
36
+ # The samples cover a mix of makes and production years so that range and make-based queries
37
+ # return non-trivial results out of the box.
38
+ #
39
+ # @author graftcode
40
+ # @since 0.2.1
41
+ def initialize
42
+ self.class.instance_variable_set(:@total_instances_created, self.class.total_instances_created + 1)
43
+ @store = {}
44
+
45
+ samples = [
46
+ SimpleCar.new("Toyota", "Corolla", 2018, "0"),
47
+ SimpleCar.new("Tesla", "Model 3", 2021, "1"),
48
+ SimpleCar.new("Ford", "Mustang", 1967, "2"),
49
+ SimpleCar.new("Honda", "Civic", 2015, "3"),
50
+ SimpleCar.new("Chevrolet", "Camaro", 2020, "4")
51
+ ]
52
+
53
+ samples.each { |car| add(car) }
54
+ end
55
+
56
+ # ── CRUD ────────────────────────────────────────────────────
57
+
58
+ # Adds a new car to the repository.
59
+ #
60
+ # The check for duplicates and the insert happen atomically, so concurrent calls cannot create
61
+ # two entries for the same id.
62
+ #
63
+ # @param car [SimpleCar] Car to add; must not be nil.
64
+ # @raise [ArgumentError] If car is nil or a car with the same id already exists.
65
+ # @return [void]
66
+ def add(car)
67
+ raise ArgumentError, "car cannot be nil" if car.nil?
68
+ raise ArgumentError, "SimpleCar with Id #{car.id} already exists." if @store.key?(car.id)
69
+
70
+ @store[car.id] = car
71
+ end
72
+
73
+ # Adds a range of simple cars to the repository.
74
+ #
75
+ # @param cars [Array<SimpleCar>] Array of cars to add.
76
+ # @raise [ArgumentError] If cars is nil or any car has an id that already exists.
77
+ # @return [void]
78
+ def add_range(cars)
79
+ raise ArgumentError, "cars cannot be nil" if cars.nil?
80
+
81
+ cars.each { |car| add(car) }
82
+ end
83
+
84
+ # Gets a simple car by its string identifier.
85
+ #
86
+ # @param id [String] The simple car identifier.
87
+ # @return [SimpleCar, nil] The matching SimpleCar if found; otherwise nil.
88
+ # @raise [ArgumentError] If id is nil or whitespace.
89
+ def get(id)
90
+ raise ArgumentError, "id cannot be nil or whitespace" if id.nil? || id.strip.empty?
91
+
92
+ @store[id]
93
+ end
94
+
95
+ # Returns all simple cars in the repository.
96
+ #
97
+ # @return [Array<SimpleCar>] A list of SimpleCar.
98
+ def get_all
99
+ @store.values
100
+ end
101
+
102
+ # Updates an existing simple car in the repository.
103
+ #
104
+ # @param car [SimpleCar] The simple car with updated data.
105
+ # @return [Boolean] true if the car was updated; otherwise false (not found).
106
+ # @raise [ArgumentError] If car is nil.
107
+ def update(car)
108
+ raise ArgumentError, "car cannot be nil" if car.nil?
109
+
110
+ return false unless @store.key?(car.id)
111
+
112
+ @store[car.id] = car
113
+ true
114
+ end
115
+
116
+ # Deletes a simple car by its string identifier.
117
+ #
118
+ # @param id [String] The simple car identifier.
119
+ # @return [Boolean] true if the car was removed; otherwise false.
120
+ # @raise [ArgumentError] If id is nil or whitespace.
121
+ def delete(id)
122
+ raise ArgumentError, "id cannot be nil or whitespace" if id.nil? || id.strip.empty?
123
+
124
+ return false unless @store.key?(id)
125
+
126
+ @store.delete(id)
127
+ true
128
+ end
129
+
130
+ # ── queries returning complex types ─────────────────────────
131
+
132
+ # Finds every car whose manufacturer matches make (case-insensitive).
133
+ #
134
+ # @param make [String] Manufacturer name to match; must not be empty.
135
+ # @return [Array<SimpleCar>] Matching cars; empty array when none match.
136
+ # @raise [ArgumentError] If make is nil or whitespace.
137
+ def find_by_make(make)
138
+ raise ArgumentError, "make cannot be nil or whitespace" if make.nil? || make.strip.empty?
139
+
140
+ lower_make = make.downcase
141
+ @store.values.select { |c| c.make.downcase == lower_make }
142
+ end
143
+
144
+ # Finds all simple cars whose production year falls within the inclusive range.
145
+ #
146
+ # @param min_year [Integer] Minimum year (inclusive).
147
+ # @param max_year [Integer] Maximum year (inclusive).
148
+ # @return [Array<SimpleCar>] Cars within the given year range.
149
+ def find_by_year_range(min_year, max_year)
150
+ @store.values.select { |c| c.year >= min_year && c.year <= max_year }
151
+ end
152
+
153
+ # ── queries returning primitive arrays ──────────────────────
154
+
155
+ # Returns all distinct production years currently stored, ascending.
156
+ #
157
+ # @return [Array<Integer>] Sorted list of distinct years.
158
+ def get_years
159
+ @store.values.map(&:year).uniq.sort
160
+ end
161
+
162
+ # Returns every distinct manufacturer present in the repository.
163
+ #
164
+ # @deprecated Prefer querying makes from a domain-specific service in new code.
165
+ # @return [Array<String>] Sorted list of unique manufacturer names.
166
+ def get_makes
167
+ @store.values.map(&:make).uniq.sort
168
+ end
169
+
170
+ # ── bulk operations with primitive-array input ──────────────
171
+
172
+ # Removes every car whose id is listed in ids.
173
+ #
174
+ # Missing ids are silently skipped; the return value reports how many entries were actually removed.
175
+ #
176
+ # @param ids [Array<String>] Identifiers to remove; nil is rejected.
177
+ # @return [Integer] Number of cars actually removed.
178
+ # @raise [ArgumentError] If ids is nil.
179
+ # @author graftcode
180
+ # @since 0.2.1
181
+ def delete_by_ids(ids)
182
+ raise ArgumentError, "ids cannot be nil" if ids.nil?
183
+
184
+ count = 0
185
+ ids.each do |id|
186
+ if @store.key?(id)
187
+ @store.delete(id)
188
+ count += 1
189
+ end
190
+ end
191
+ count
192
+ end
193
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sdn_test_simple_car_repository
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - GraftCode