pilipinas 1.0.0 → 1.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: 4a0d4e9bce22ec277d0dc496465c5f78ac9f6470c8ea579832191b2bcecba289
4
- data.tar.gz: 188a8a2c3d853c01da1eaa3d0609688b0a6612cd0db46fe600b5754d58864753
3
+ metadata.gz: 3191d97a140c01be0e95c6f1045d54fbd4e4e4ca0bf84783520d67c865376dee
4
+ data.tar.gz: 8216cefb4c6d5d81af30087d6f13a32f5feb79b729f74c194f00c17da7c37e2e
5
5
  SHA512:
6
- metadata.gz: c4d3910367c067e84aaae374d27a39de44acaf1eba461150f84e019f8e9e0f6fb0ff2341fe44101e4cfb3c7c3ac0b7a23495d8d285adf7ad53af96bccc51285e
7
- data.tar.gz: f17c36621d5afce588b5bcf95eea17cea461abb0d5c2dfc6caac8b8905c5e9fe71827f33e469dc3616ca40f188f030544776393c921af7e6fa40f0d9339af658
6
+ metadata.gz: 4a917e6a92b3f12506b6cf08e7c09c2cd37a6db31bdf6f8d6fb6cd9b1317fa1f23002e4839829ba023a6aeb80e68f74c92a91feb66bc0c4d6a9c8ed0178209e7
7
+ data.tar.gz: faea923c4f805a2b2cbb43d89676cb66b95c2e9df643f6aedb8125c4d1cd8d1cad1f0a946d39a70a8edac2d165d068ec1e06046d33390d3cff481e60cabeded5
data/CHANGELOG.md ADDED
@@ -0,0 +1,79 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ ## [1.1.0] - 2026-05-13
11
+
12
+ ### Added
13
+
14
+ - `enforce_readonly` class attribute on the `StaticRecord` concern (default: `true`).
15
+ Subclasses can opt out of the read-only guard without stubbing:
16
+ ```ruby
17
+ class Locations::Barangay < Pilipinas::Db::Barangay
18
+ self.enforce_readonly = false
19
+ end
20
+ ```
21
+ - `lib/pilipinas/testing/rspec.rb` — a ready-made RSpec helper that disables
22
+ the read-only guard on all four DB models for the entire test suite.
23
+ Require it once in `rails_helper.rb`:
24
+ ```ruby
25
+ require 'pilipinas/testing/rspec'
26
+ ```
27
+ - Spec coverage for `StaticRecord` — 8 examples covering default behaviour,
28
+ `enforce_readonly = false`, subclass inheritance, and class-level isolation.
29
+
30
+ ### Changed
31
+
32
+ - `readonly?` now gates on `self.class.enforce_readonly && !new_record?` instead
33
+ of unconditionally returning `!new_record?`.
34
+
35
+ ---
36
+
37
+ ## [1.0.0] - 2026-05-12
38
+
39
+ Complete rewrite of the gem. Zero runtime dependencies.
40
+
41
+ ### Added
42
+
43
+ - In-memory layer with thread-safe `Pilipinas::Cache` (Mutex + double-checked
44
+ locking) and O(1) look-ups via separate code/name hash indices.
45
+ - Immutable value objects — every entity instance is frozen.
46
+ - `Pilipinas::Region`, `Province`, `City`, `Barangay` with `.all`, `.count`,
47
+ `.first`, `.last`, `.find_by`, `.find_by_code`, `.find_by_name`.
48
+ - Hierarchy traversal: `region.provinces`, `province.cities`, `city.barangays`.
49
+ - Optional ActiveRecord layer (`Pilipinas::Db::*`) with memory-efficient scopes
50
+ (`.lite`, `.by_code`, `.by_name`, `.find_lite_by_code`, `.find_lite_by_name`).
51
+ - `StaticRecord` concern: disables STI, adds lean SELECT scopes, enforces
52
+ read-only on persisted records.
53
+ - Migration generator (`rails generate pilipinas:migration`) and
54
+ `rake pilipinas:load` seeding task.
55
+ - Full RSpec suite (57 examples).
56
+ - GitHub Actions CI pipeline.
57
+
58
+ ### Changed
59
+
60
+ - Requires Ruby ≥ 3.4 (developed against Ruby 4.0).
61
+ - Removed all runtime gem dependencies (previously depended on `yaml_db` and
62
+ others).
63
+
64
+ ---
65
+
66
+ ## [0.0.1] - 2019-01-26
67
+
68
+ ### Added
69
+
70
+ - Initial release.
71
+ - YAML data for Philippine regions, provinces, cities, and barangays.
72
+ - ActiveRecord models backed by `pilipinas_*` tables.
73
+ - Migration template and Rake loader task.
74
+ - Rails generator for migrations.
75
+ - Railtie for automatic Rake task loading in Rails apps.
76
+
77
+ [1.1.0]: https://github.com/denmarkmeralpis/pilipinas/compare/v1.0.0...v1.1.0
78
+ [1.0.0]: https://github.com/denmarkmeralpis/pilipinas/compare/v0.0.1...v1.0.0
79
+ [0.0.1]: https://github.com/denmarkmeralpis/pilipinas/releases/tag/v0.0.1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pilipinas (1.0.0)
4
+ pilipinas (1.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -295,7 +295,7 @@ CHECKSUMS
295
295
  nokogiri (1.19.3-x86_64-linux-musl) sha256=248c906d2166eca5efb56d52fdee5f9a1f51d69a72e2b64fdac647b4ce39ea3f
296
296
  parallel (2.1.0) sha256=b35258865c2e31134c5ecb708beaaf6772adf9d5efae28e93e99260877b09356
297
297
  parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54
298
- pilipinas (1.0.0)
298
+ pilipinas (1.1.0)
299
299
  pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
300
300
  prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
301
301
  prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
data/README.md CHANGED
@@ -18,6 +18,8 @@ Region → Province → City / Municipality → Barangay
18
18
  - **O(1) look-ups** — separate hash indices keyed by code and by name; no linear scans.
19
19
  - **Immutable value objects** — every entity instance is frozen. Safe to share across threads and fibers without copying.
20
20
  - **Optional ActiveRecord integration** — a migration generator and Rake task seed the four `pilipinas_*` tables from the bundled YAML data.
21
+ - **Read-only by default** — persisted AR model instances raise `ActiveRecord::ReadOnlyRecord` on accidental writes; opt out per-class via `enforce_readonly = false`.
22
+ - **Test helper included** — `require 'pilipinas/testing/rspec'` disables the read-only guard for the entire RSpec suite with one line.
21
23
  - **Ruby ≥ 3.4** required; developed against Ruby 4.0.
22
24
 
23
25
  ---
@@ -184,6 +186,48 @@ province.cities # has_many association
184
186
 
185
187
  > **Note:** The AR models are auto-loaded and require `activerecord` to be available.
186
188
 
189
+ ### Read-only behaviour
190
+
191
+ All four `Pilipinas::Db::*` models are **read-only by default**. Any attempt to call `update!`, `save`, or `destroy` on a persisted record raises `ActiveRecord::ReadOnlyRecord`. This is intentional — the pilipinas tables are static reference data that should never be mutated after seeding.
192
+
193
+ New (unsaved) records are always writable, so `create!` works normally in the Loader and in test factories.
194
+
195
+ #### Opting a subclass out of read-only enforcement
196
+
197
+ If your application inherits from a Pilipinas DB model and legitimately needs write access, set `enforce_readonly` to `false` on the subclass:
198
+
199
+ ```ruby
200
+ class Locations::Barangay < Pilipinas::Db::Barangay
201
+ self.enforce_readonly = false
202
+ end
203
+ ```
204
+
205
+ This does not affect the parent class or any other model.
206
+
207
+ ---
208
+
209
+ ## Testing
210
+
211
+ The gem ships a ready-made RSpec helper that turns off the read-only guard for the entire test suite — no stubbing required.
212
+
213
+ ```ruby
214
+ # spec/rails_helper.rb (or spec/support/pilipinas.rb)
215
+ require 'pilipinas/testing/rspec'
216
+ ```
217
+
218
+ This sets `enforce_readonly = false` on all four models (`Region`, `Province`, `City`, `Barangay`) inside a `before(:suite)` hook, so FactoryBot factories, fixtures, and any spec that writes to pilipinas tables work without extra setup.
219
+
220
+ If you only need writable records in a specific context:
221
+
222
+ ```ruby
223
+ around do |example|
224
+ Locations::Barangay.enforce_readonly = false
225
+ example.run
226
+ ensure
227
+ Locations::Barangay.enforce_readonly = true
228
+ end
229
+ ```
230
+
187
231
  ---
188
232
 
189
233
  ## Advanced
@@ -238,54 +282,8 @@ The gem is available as open source under the terms of the [MIT License](LICENSE
238
282
 
239
283
  ## Acknowledgements
240
284
 
241
- The geographic data used in this gem is derived from the Philippine Standard Geographic Code (PSGC) published by the Philippine Statistics Authority.
242
-
243
-
244
- ## Installation
245
-
246
- Add this line to your application's Gemfile:
247
-
248
- ```ruby
249
- gem 'pilipinas'
250
- ```
251
-
252
- And then execute:
253
-
254
- $ bundle
255
-
256
- Or install it yourself as:
257
-
258
- $ gem install pilipinas
259
-
260
- ## Usage
261
-
262
- ```ruby
263
- # All Regions
264
- Pilipinas::Region.all
265
-
266
- # All Provinces
267
- Pilipinas::Province.all
268
-
269
- # All Cities/Municipalities
270
- Pilipinas::City.all
271
-
272
- # All Barangays
273
- Pilipinas::Barangay.all
274
-
275
- # Finding record thru find_by_(code/name) method
276
- region = Pilipinas::Region.find_by_name("REGION V (Bicol Region)")
277
-
278
- # Get provinces by region
279
- region.provinces
280
- ```
281
- ## Acknowledgement
282
-
283
285
  The data used in this gem is from `gem pinas`. Kudos!
284
286
 
285
- ## TODO
286
-
287
- * Add a form helper
288
-
289
287
  ## Development
290
288
 
291
289
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -25,10 +25,14 @@ module Pilipinas
25
25
  #
26
26
  # == Optimizations applied
27
27
  #
28
- # * +readonly?+ returns +true+ for persisted records only — accidental
28
+ # * +readonly?+ returns +true+ for persisted records when
29
+ # +enforce_readonly+ is +true+ (the default) — accidental
29
30
  # +update!/save!/destroy+ on fetched rows raise
30
31
  # +ActiveRecord::ReadOnlyRecord+; new records stay writable so the
31
32
  # Loader and test fixtures can still call +create!+.
33
+ # * +enforce_readonly+ class attribute: opt a subclass out of the
34
+ # read-only guard without touching production models — useful in test
35
+ # environments where factories need to write to pilipinas tables.
32
36
  # * +self.inheritance_column = :_sti_disabled+: removes STI type-column
33
37
  # look-up from every query.
34
38
  # * +.lite+ scope: selects only +id+, +location_id+, +code+, +name+ —
@@ -50,6 +54,11 @@ module Pilipinas
50
54
  # province.cities # SELECT id, location_id, parent_id, code, name …
51
55
  # city.barangays # SELECT id, location_id, parent_id, code, name …
52
56
  #
57
+ # @example Opting a subclass out of read-only enforcement (e.g. in tests)
58
+ # class Locations::Barangay < Pilipinas::Db::Barangay
59
+ # self.enforce_readonly = false
60
+ # end
61
+ #
53
62
  module StaticRecord
54
63
  extend ActiveSupport::Concern
55
64
 
@@ -64,6 +73,16 @@ module Pilipinas
64
73
  # Removes the hidden "type" column check AR performs on every query.
65
74
  self.inheritance_column = :_sti_disabled
66
75
 
76
+ # ── Read-only enforcement ─────────────────────────────────────────
77
+ # Defaults to +true+. Set to +false+ on a subclass (e.g. in a test
78
+ # environment or for a model that legitimately needs write access)
79
+ # without touching production behaviour:
80
+ #
81
+ # class Locations::Barangay < Pilipinas::Db::Barangay
82
+ # self.enforce_readonly = false
83
+ # end
84
+ class_attribute :enforce_readonly, instance_writer: false, default: true
85
+
67
86
  # ── Memory-efficient query scopes ─────────────────────────────────
68
87
 
69
88
  # Select only the four columns needed for display and look-up.
@@ -97,19 +116,25 @@ module Pilipinas
97
116
  scope :find_lite_by_name, ->(name) { lite.by_name(name).first }
98
117
  end
99
118
 
100
- # Persisted instances loaded from a pilipinas_* table are permanently
101
- # read-only: +update!+, +save+, and +destroy+ all raise
102
- # +ActiveRecord::ReadOnlyRecord+. New (unsaved) objects are writable
103
- # so that the Loader can still call +create!+ on the fallback path and
104
- # so that specs can build fixtures with +create!+.
119
+ # Guards against accidental writes to static reference data.
120
+ #
121
+ # Returns +true+ (making the record read-only) when both conditions hold:
122
+ # 1. The record is persisted (+new_record?+ is +false+).
123
+ # 2. The class-level +enforce_readonly+ flag is +true+ (the default).
124
+ #
125
+ # New (unsaved) objects are always writable so the Loader and test
126
+ # factories can call +create!+. To allow writes on a subclass — for
127
+ # example in a test environment — set:
128
+ #
129
+ # self.enforce_readonly = false
105
130
  #
106
131
  # Overriding +readonly?+ is more efficient than an +after_initialize+
107
- # callback because it is only called when AR is about to perform a
108
- # write operation it adds zero per-record overhead on reads.
132
+ # callback: it is only invoked when AR is about to perform a write
133
+ # operation, so it adds zero overhead on read paths.
109
134
  #
110
- # @return [Boolean] +true+ for persisted records, +false+ for new ones
135
+ # @return [Boolean]
111
136
  def readonly?
112
- !new_record?
137
+ self.class.enforce_readonly && !new_record?
113
138
  end
114
139
  end
115
140
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pilipinas'
4
+
5
+ # Pilipinas::Testing::RSpec
6
+ #
7
+ # Optional RSpec helper that disables the read-only guard on all Pilipinas DB
8
+ # models for the duration of the test suite. Require this file once (e.g. in
9
+ # +rails_helper.rb+ or +spec/support/pilipinas.rb+) and FactoryBot factories,
10
+ # fixtures, or any spec that needs to write to pilipinas_* tables will work
11
+ # without stubbing or subclass overrides.
12
+ #
13
+ # == Usage
14
+ #
15
+ # # spec/rails_helper.rb (or spec/support/pilipinas.rb)
16
+ # require 'pilipinas/testing/rspec'
17
+ #
18
+ # == What it does
19
+ #
20
+ # Calls +enforce_readonly = false+ on every Pilipinas DB model inside a
21
+ # +before(:suite)+ hook so the flag is set once, before any example runs.
22
+ # The models remain writable for the entire test process, which is the correct
23
+ # behaviour for a test environment where factories seed the pilipinas_* tables.
24
+ #
25
+ # If you need write access only in a specific context, set the flag manually
26
+ # with an +around+ hook instead of requiring this file globally.
27
+ #
28
+ # == Models affected
29
+ #
30
+ # * Pilipinas::Db::Region
31
+ # * Pilipinas::Db::Province
32
+ # * Pilipinas::Db::City
33
+ # * Pilipinas::Db::Barangay
34
+
35
+ require 'rspec/core'
36
+
37
+ RSpec.configure do |config|
38
+ config.before(:suite) do
39
+ [
40
+ Pilipinas::Db::Region,
41
+ Pilipinas::Db::Province,
42
+ Pilipinas::Db::City,
43
+ Pilipinas::Db::Barangay
44
+ ].each { |model| model.enforce_readonly = false }
45
+ end
46
+ end
@@ -4,5 +4,5 @@ module Pilipinas
4
4
  # Semantic version of the gem.
5
5
  #
6
6
  # Follows {https://semver.org Semantic Versioning}: MAJOR.MINOR.PATCH.
7
- VERSION = '1.0.0'
7
+ VERSION = '1.1.0'
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pilipinas
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nujian Den Mark Meralpis
@@ -143,6 +143,7 @@ executables: []
143
143
  extensions: []
144
144
  extra_rdoc_files: []
145
145
  files:
146
+ - CHANGELOG.md
146
147
  - CODE_OF_CONDUCT.md
147
148
  - Gemfile
148
149
  - Gemfile.lock
@@ -1924,6 +1925,7 @@ files:
1924
1925
  - lib/pilipinas/province.rb
1925
1926
  - lib/pilipinas/railtie.rb
1926
1927
  - lib/pilipinas/region.rb
1928
+ - lib/pilipinas/testing/rspec.rb
1927
1929
  - lib/pilipinas/version.rb
1928
1930
  - lib/tasks/pilipinas_tasks.rake
1929
1931
  - pilipinas.gemspec