jp_address_complement 0.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.
Files changed (181) hide show
  1. checksums.yaml +7 -0
  2. data/.agent/rules/specify-rules.md +29 -0
  3. data/.agent/workflows/speckit.analyze.md +184 -0
  4. data/.agent/workflows/speckit.checklist.md +294 -0
  5. data/.agent/workflows/speckit.clarify.md +181 -0
  6. data/.agent/workflows/speckit.constitution.md +84 -0
  7. data/.agent/workflows/speckit.implement.md +135 -0
  8. data/.agent/workflows/speckit.plan.md +90 -0
  9. data/.agent/workflows/speckit.specify.md +258 -0
  10. data/.agent/workflows/speckit.tasks.md +137 -0
  11. data/.agent/workflows/speckit.taskstoissues.md +30 -0
  12. data/.claude/commands/speckit.analyze.md +184 -0
  13. data/.claude/commands/speckit.checklist.md +294 -0
  14. data/.claude/commands/speckit.clarify.md +181 -0
  15. data/.claude/commands/speckit.constitution.md +84 -0
  16. data/.claude/commands/speckit.implement.md +135 -0
  17. data/.claude/commands/speckit.plan.md +90 -0
  18. data/.claude/commands/speckit.specify.md +258 -0
  19. data/.claude/commands/speckit.tasks.md +137 -0
  20. data/.claude/commands/speckit.taskstoissues.md +30 -0
  21. data/.cursor/commands/speckit.analyze.md +184 -0
  22. data/.cursor/commands/speckit.checklist.md +294 -0
  23. data/.cursor/commands/speckit.clarify.md +181 -0
  24. data/.cursor/commands/speckit.constitution.md +84 -0
  25. data/.cursor/commands/speckit.implement.md +135 -0
  26. data/.cursor/commands/speckit.plan.md +90 -0
  27. data/.cursor/commands/speckit.specify.md +258 -0
  28. data/.cursor/commands/speckit.tasks.md +137 -0
  29. data/.cursor/commands/speckit.taskstoissues.md +30 -0
  30. data/.cursor/rules/specify-rules.mdc +32 -0
  31. data/.rubocop.yml +118 -0
  32. data/.specify/memory/constitution.md +130 -0
  33. data/.specify/scripts/bash/check-prerequisites.sh +166 -0
  34. data/.specify/scripts/bash/common.sh +156 -0
  35. data/.specify/scripts/bash/create-new-feature.sh +297 -0
  36. data/.specify/scripts/bash/setup-plan.sh +61 -0
  37. data/.specify/scripts/bash/update-agent-context.sh +810 -0
  38. data/.specify/templates/agent-file-template.md +28 -0
  39. data/.specify/templates/checklist-template.md +40 -0
  40. data/.specify/templates/constitution-template.md +50 -0
  41. data/.specify/templates/plan-template.md +104 -0
  42. data/.specify/templates/spec-template.md +115 -0
  43. data/.specify/templates/tasks-template.md +251 -0
  44. data/CHANGELOG.md +26 -0
  45. data/LICENSE +9 -0
  46. data/README.md +274 -0
  47. data/Rakefile +19 -0
  48. data/Steepfile +9 -0
  49. data/examples/rails/jp_address_complement_demo/.gitignore +15 -0
  50. data/examples/rails/jp_address_complement_demo/.ruby-version +1 -0
  51. data/examples/rails/jp_address_complement_demo/Gemfile +22 -0
  52. data/examples/rails/jp_address_complement_demo/Gemfile.lock +252 -0
  53. data/examples/rails/jp_address_complement_demo/README.md +57 -0
  54. data/examples/rails/jp_address_complement_demo/Rakefile +6 -0
  55. data/examples/rails/jp_address_complement_demo/app/assets/images/.keep +0 -0
  56. data/examples/rails/jp_address_complement_demo/app/assets/stylesheets/application.css +1 -0
  57. data/examples/rails/jp_address_complement_demo/app/controllers/addresses_controller.rb +59 -0
  58. data/examples/rails/jp_address_complement_demo/app/controllers/application_controller.rb +4 -0
  59. data/examples/rails/jp_address_complement_demo/app/controllers/concerns/.keep +0 -0
  60. data/examples/rails/jp_address_complement_demo/app/helpers/application_helper.rb +2 -0
  61. data/examples/rails/jp_address_complement_demo/app/models/application_record.rb +3 -0
  62. data/examples/rails/jp_address_complement_demo/app/models/concerns/.keep +0 -0
  63. data/examples/rails/jp_address_complement_demo/app/views/addresses/index.html.erb +22 -0
  64. data/examples/rails/jp_address_complement_demo/app/views/addresses/prefecture.html.erb +20 -0
  65. data/examples/rails/jp_address_complement_demo/app/views/addresses/prefix.html.erb +25 -0
  66. data/examples/rails/jp_address_complement_demo/app/views/addresses/reverse.html.erb +30 -0
  67. data/examples/rails/jp_address_complement_demo/app/views/addresses/validate.html.erb +23 -0
  68. data/examples/rails/jp_address_complement_demo/app/views/layouts/application.html.erb +40 -0
  69. data/examples/rails/jp_address_complement_demo/app/views/pwa/manifest.json.erb +22 -0
  70. data/examples/rails/jp_address_complement_demo/app/views/pwa/service-worker.js +26 -0
  71. data/examples/rails/jp_address_complement_demo/bin/ci +6 -0
  72. data/examples/rails/jp_address_complement_demo/bin/dev +2 -0
  73. data/examples/rails/jp_address_complement_demo/bin/rails +4 -0
  74. data/examples/rails/jp_address_complement_demo/bin/rake +4 -0
  75. data/examples/rails/jp_address_complement_demo/bin/setup +35 -0
  76. data/examples/rails/jp_address_complement_demo/config/application.rb +42 -0
  77. data/examples/rails/jp_address_complement_demo/config/boot.rb +3 -0
  78. data/examples/rails/jp_address_complement_demo/config/ci.rb +15 -0
  79. data/examples/rails/jp_address_complement_demo/config/credentials.yml.enc +1 -0
  80. data/examples/rails/jp_address_complement_demo/config/database.yml +31 -0
  81. data/examples/rails/jp_address_complement_demo/config/environment.rb +5 -0
  82. data/examples/rails/jp_address_complement_demo/config/environments/development.rb +54 -0
  83. data/examples/rails/jp_address_complement_demo/config/environments/production.rb +67 -0
  84. data/examples/rails/jp_address_complement_demo/config/environments/test.rb +42 -0
  85. data/examples/rails/jp_address_complement_demo/config/initializers/content_security_policy.rb +29 -0
  86. data/examples/rails/jp_address_complement_demo/config/initializers/filter_parameter_logging.rb +8 -0
  87. data/examples/rails/jp_address_complement_demo/config/initializers/inflections.rb +16 -0
  88. data/examples/rails/jp_address_complement_demo/config/locales/en.yml +31 -0
  89. data/examples/rails/jp_address_complement_demo/config/puma.rb +39 -0
  90. data/examples/rails/jp_address_complement_demo/config/routes.rb +19 -0
  91. data/examples/rails/jp_address_complement_demo/config.ru +6 -0
  92. data/examples/rails/jp_address_complement_demo/db/migrate/20260228083709_create_jp_address_complement_postal_codes.rb +44 -0
  93. data/examples/rails/jp_address_complement_demo/db/schema.rb +33 -0
  94. data/examples/rails/jp_address_complement_demo/db/seeds.rb +24 -0
  95. data/examples/rails/jp_address_complement_demo/lib/tasks/.keep +0 -0
  96. data/examples/rails/jp_address_complement_demo/log/.keep +0 -0
  97. data/examples/rails/jp_address_complement_demo/public/400.html +135 -0
  98. data/examples/rails/jp_address_complement_demo/public/404.html +135 -0
  99. data/examples/rails/jp_address_complement_demo/public/406-unsupported-browser.html +135 -0
  100. data/examples/rails/jp_address_complement_demo/public/422.html +135 -0
  101. data/examples/rails/jp_address_complement_demo/public/500.html +135 -0
  102. data/examples/rails/jp_address_complement_demo/public/icon.png +0 -0
  103. data/examples/rails/jp_address_complement_demo/public/icon.svg +3 -0
  104. data/examples/rails/jp_address_complement_demo/public/robots.txt +1 -0
  105. data/examples/rails/jp_address_complement_demo/script/.keep +0 -0
  106. data/examples/rails/jp_address_complement_demo/storage/.keep +0 -0
  107. data/examples/rails/jp_address_complement_demo/vendor/.keep +0 -0
  108. data/lib/generators/jp_address_complement/install_generator.rb +34 -0
  109. data/lib/generators/jp_address_complement/templates/create_jp_address_complement_postal_codes.rb.erb +45 -0
  110. data/lib/jp_address_complement/address_record.rb +36 -0
  111. data/lib/jp_address_complement/configuration.rb +21 -0
  112. data/lib/jp_address_complement/importers/csv_importer.rb +148 -0
  113. data/lib/jp_address_complement/ken_all_downloader.rb +122 -0
  114. data/lib/jp_address_complement/models/postal_code.rb +21 -0
  115. data/lib/jp_address_complement/normalizer.rb +77 -0
  116. data/lib/jp_address_complement/prefecture.rb +105 -0
  117. data/lib/jp_address_complement/railtie.rb +27 -0
  118. data/lib/jp_address_complement/repositories/active_record_postal_code_repository.rb +78 -0
  119. data/lib/jp_address_complement/repositories/csv_postal_code_repository.rb +200 -0
  120. data/lib/jp_address_complement/repositories/postal_code_repository.rb +36 -0
  121. data/lib/jp_address_complement/searcher.rb +85 -0
  122. data/lib/jp_address_complement/validators/address_validator.rb +41 -0
  123. data/lib/jp_address_complement/version.rb +6 -0
  124. data/lib/jp_address_complement.rb +129 -0
  125. data/lib/tasks/jp_address_complement.rake +32 -0
  126. data/rbs_collection.lock.yaml +380 -0
  127. data/rbs_collection.yaml +19 -0
  128. data/sig/generated/generators/jp_address_complement/install_generator.rbs +18 -0
  129. data/sig/generated/jp_address_complement/configuration.rbs +18 -0
  130. data/sig/generated/jp_address_complement/importers/csv_importer.rbs +78 -0
  131. data/sig/generated/jp_address_complement/ken_all_downloader.rbs +49 -0
  132. data/sig/generated/jp_address_complement/normalizer.rbs +37 -0
  133. data/sig/generated/jp_address_complement/prefecture.rbs +27 -0
  134. data/sig/generated/jp_address_complement/railtie.rbs +8 -0
  135. data/sig/generated/jp_address_complement/repositories/active_record_postal_code_repository.rbs +38 -0
  136. data/sig/generated/jp_address_complement/repositories/csv_postal_code_repository.rbs +100 -0
  137. data/sig/generated/jp_address_complement/repositories/postal_code_repository.rbs +29 -0
  138. data/sig/generated/jp_address_complement/searcher.rbs +43 -0
  139. data/sig/generated/jp_address_complement/validators/address_validator.rbs +24 -0
  140. data/sig/generated/jp_address_complement/version.rbs +5 -0
  141. data/sig/generated/jp_address_complement.rbs +84 -0
  142. data/sig/manual/address_record.rbs +40 -0
  143. data/sig/manual/gem_rubyzip.rbs +17 -0
  144. data/sig/manual/postal_code.rbs +9 -0
  145. data/sig/manual/stdlib_csv_invalid_encoding_error.rbs +5 -0
  146. data/sig/manual/stdlib_net_http.rbs +33 -0
  147. data/sig/manual/stdlib_openuri.rbs +9 -0
  148. data/sig/manual/stdlib_tmpdir.rbs +4 -0
  149. data/specs/001-jp-address-complement-gem/checklists/requirements.md +36 -0
  150. data/specs/001-jp-address-complement-gem/contracts/public-api.md +209 -0
  151. data/specs/001-jp-address-complement-gem/data-model.md +207 -0
  152. data/specs/001-jp-address-complement-gem/plan.md +124 -0
  153. data/specs/001-jp-address-complement-gem/quickstart.md +151 -0
  154. data/specs/001-jp-address-complement-gem/research.md +139 -0
  155. data/specs/001-jp-address-complement-gem/spec.md +153 -0
  156. data/specs/001-jp-address-complement-gem/tasks.md +279 -0
  157. data/specs/002-rbs-type-annotations/checklists/requirements.md +37 -0
  158. data/specs/002-rbs-type-annotations/contracts/rbs-public-api.md +116 -0
  159. data/specs/002-rbs-type-annotations/data-model.md +119 -0
  160. data/specs/002-rbs-type-annotations/plan.md +116 -0
  161. data/specs/002-rbs-type-annotations/quickstart.md +105 -0
  162. data/specs/002-rbs-type-annotations/research.md +173 -0
  163. data/specs/002-rbs-type-annotations/spec.md +125 -0
  164. data/specs/002-rbs-type-annotations/tasks.md +189 -0
  165. data/specs/003-csv-remove-obsolete/checklists/requirements.md +34 -0
  166. data/specs/003-csv-remove-obsolete/contracts/csv-import.md +41 -0
  167. data/specs/003-csv-remove-obsolete/data-model.md +47 -0
  168. data/specs/003-csv-remove-obsolete/plan.md +73 -0
  169. data/specs/003-csv-remove-obsolete/quickstart.md +40 -0
  170. data/specs/003-csv-remove-obsolete/research.md +71 -0
  171. data/specs/003-csv-remove-obsolete/spec.md +85 -0
  172. data/specs/003-csv-remove-obsolete/tasks.md +167 -0
  173. data/specs/004-prefecture-code-reverse-lookup/checklists/requirements.md +34 -0
  174. data/specs/004-prefecture-code-reverse-lookup/contracts/public-api-prefecture-and-reverse.md +122 -0
  175. data/specs/004-prefecture-code-reverse-lookup/data-model.md +81 -0
  176. data/specs/004-prefecture-code-reverse-lookup/plan.md +92 -0
  177. data/specs/004-prefecture-code-reverse-lookup/quickstart.md +91 -0
  178. data/specs/004-prefecture-code-reverse-lookup/research.md +62 -0
  179. data/specs/004-prefecture-code-reverse-lookup/spec.md +120 -0
  180. data/specs/004-prefecture-code-reverse-lookup/tasks.md +190 -0
  181. metadata +451 -0
@@ -0,0 +1,18 @@
1
+ # Generated from lib/generators/jp_address_complement/install_generator.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ module Generators
5
+ # `rails g jp_address_complement:install` で呼び出されるジェネレーター
6
+ # 住所テーブル用マイグレーションファイルを利用者アプリの db/migrate/ に生成する
7
+ class InstallGenerator < Rails::Generators::Base
8
+ include Rails::Generators::Migration
9
+
10
+ # Rails::Generators::Base の RBS に next_migration_number 等が未定義のため steep:ignore
11
+ # @rbs (String dirname) -> String
12
+ def self.next_migration_number: (String dirname) -> String
13
+
14
+ # @rbs () -> void
15
+ def create_migration_file: () -> void
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # Generated from lib/jp_address_complement/configuration.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ # Gem の設定を保持するクラス
5
+ # configure ブロックを通じて repository アダプター・PostalCode の継承元などを注入する
6
+ class Configuration
7
+ attr_accessor repository: Repositories::PostalCodeRepository?
8
+
9
+ # PostalCode モデルの継承元。nil のときは ActiveRecord::Base。initializer で ApplicationRecord 等に変更可能。
10
+ attr_accessor postal_code_model_base: Class?
11
+
12
+ # PostalCode が参照するテーブル名。nil のときは 'jp_address_complement_postal_codes'。initializer で変更可能。
13
+ attr_accessor postal_code_table_name: String?
14
+
15
+ # @rbs () -> void
16
+ def initialize: () -> void
17
+ end
18
+ end
@@ -0,0 +1,78 @@
1
+ # Generated from lib/jp_address_complement/importers/csv_importer.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ module Importers
5
+ # インポート結果(件数報告用)
6
+ # @rbs type upserted = Integer
7
+ # @rbs type deleted = Integer
8
+ class ImportResult < Data
9
+ attr_reader upserted(): untyped
10
+
11
+ attr_reader deleted(): untyped
12
+
13
+ def self.new: (untyped upserted, untyped deleted) -> instance
14
+ | (upserted: untyped, deleted: untyped) -> instance
15
+
16
+ def self.members: () -> [ :upserted, :deleted ]
17
+
18
+ def members: () -> [ :upserted, :deleted ]
19
+ end
20
+
21
+ # UTF-8 版 KEN_ALL(utf_ken_all.csv)を読み込み、jp_address_complement_postal_codes テーブルに upsert する
22
+ # UTF-8 形式の CSV を前提として処理する
23
+ class CsvImporter
24
+ BATCH_SIZE: Integer
25
+
26
+ # 列インデックス(KEN_ALL.CSV 形式)
27
+ COL_PREF_CODE: Integer
28
+
29
+ COL_POSTAL_CODE: Integer
30
+
31
+ COL_KANA_PREF: Integer
32
+
33
+ COL_KANA_CITY: Integer
34
+
35
+ COL_KANA_TOWN: Integer
36
+
37
+ COL_PREF: Integer
38
+
39
+ COL_CITY: Integer
40
+
41
+ COL_TOWN: Integer
42
+
43
+ COL_IS_PARTIAL: Integer
44
+
45
+ COL_HAS_ALIAS: Integer
46
+
47
+ COL_IS_LARGE_OFFICE: Integer
48
+
49
+ # @rbs (String csv_path) -> void
50
+ def initialize: (String csv_path) -> void
51
+
52
+ # CSV を読み込み、upsert 後に古いバージョンの行を一括削除する。戻り値は ImportResult。
53
+ # バージョンは既存レコードの最大値+1 で、別テーブルでは管理しない。
54
+ # @rbs () -> ImportResult
55
+ # @return [ImportResult] upserted 件数と deleted 件数
56
+ def import: () -> ImportResult
57
+
58
+ private
59
+
60
+ # @rbs (Array[String?] row) -> (Hash[Symbol, untyped] | nil)
61
+ def parse_row: (Array[String?] row) -> (Hash[Symbol, untyped] | nil)
62
+
63
+ # @rbs (Integer import_version) -> [Integer, Hash[untyped, bool]]
64
+ def read_and_upsert: (Integer import_version) -> [ Integer, Hash[untyped, bool] ]
65
+
66
+ # @rbs (Array[Hash[Symbol, untyped]] batch) -> void
67
+ def upsert_batch: (Array[Hash[Symbol, untyped]] batch) -> void
68
+
69
+ # 郵便番号・都道府県・市区町村・町域(漢字)が同じでも読み(カナ)が異なれば別レコードとして扱う
70
+ # @rbs (Hash[Symbol, untyped] record) -> Array[String]
71
+ def row_key: (Hash[Symbol, untyped] record) -> Array[String]
72
+
73
+ # 今回のインポートより古いバージョンの行を一括削除し、削除件数を返す
74
+ # @rbs (Integer import_version) -> Integer
75
+ def delete_obsolete: (Integer import_version) -> Integer
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,49 @@
1
+ # Generated from lib/jp_address_complement/ken_all_downloader.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ # 郵便番号データ(utf_ken_all.zip)を公式URLからダウンロードし、展開して CSV のパスを返す
5
+ class KenAllDownloader
6
+ # @rbs String
7
+ DEFAULT_URL: ::String
8
+
9
+ # @rbs String
10
+ CSV_FILENAME: ::String
11
+
12
+ class DownloadError < JpAddressComplement::Error
13
+ end
14
+
15
+ # @rbs (?String url) -> void
16
+ # @param url [String] ダウンロードする zip の URL(省略時は DEFAULT_URL)
17
+ def initialize: (?String url) -> void
18
+
19
+ # zip をダウンロードして一時ディレクトリに展開し、KEN_ALL.CSV の絶対パスを返す。
20
+ # 呼び出し元でインポート完了まで一時ディレクトリは削除されない(プロセス終了時に OS が削除)。
21
+ # @rbs () -> String
22
+ # @return [String] 展開された KEN_ALL.CSV の絶対パス
23
+ # @raise [DownloadError] ダウンロード・展開・ファイルが見つからない場合
24
+ def download_and_extract: () -> String
25
+
26
+ private
27
+
28
+ # @rbs () -> String
29
+ def download_zip: () -> String
30
+
31
+ # @rbs (String path) -> void
32
+ def fetch_to_path: (String path) -> void
33
+
34
+ # @rbs (Net::HTTPResponse response, String path) -> void
35
+ def write_response_to_path: (Net::HTTPResponse response, String path) -> void
36
+
37
+ # @rbs (String zip_path) -> String
38
+ def extract_zip: (String zip_path) -> String
39
+
40
+ # @rbs (String zip_path, String tmpdir) -> String?
41
+ def extract_zip_entries: (String zip_path, String tmpdir) -> String?
42
+
43
+ # @rbs (String entry_name, String dest) -> bool
44
+ def entry_csv?: (String entry_name, String dest) -> bool
45
+
46
+ # @rbs (String tmpdir) -> String?
47
+ def find_csv_in_dir: (String tmpdir) -> String?
48
+ end
49
+ end
@@ -0,0 +1,37 @@
1
+ # Generated from lib/jp_address_complement/normalizer.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ # 郵便番号の正規化処理を担当するクラス
5
+ # 全角→半角変換・〒記号除去・ハイフン除去を行う
6
+ class Normalizer
7
+ # 半角数字以外の文字を除去するためのパターン
8
+ DIGIT_ONLY: Regexp
9
+
10
+ PREFIX_MIN_LENGTH: Integer
11
+
12
+ # 町域から除去する「通常住所に含まれない」固定文字列(漢字・かな両方)
13
+ TOWN_DISPLAY_REMOVAL_STRINGS: untyped
14
+
15
+ # 郵便番号文字列を正規化して7桁の半角数字文字列を返す
16
+ # @rbs (String?) -> String?
17
+ # @param code [String, nil] 郵便番号文字列(ハイフン・全角・〒記号を自動除去)
18
+ # @return [String, nil] 正規化後の7桁郵便番号。不正な場合は nil
19
+ def self.normalize_postal_code: (String?) -> String?
20
+
21
+ # 郵便番号プレフィックスを正規化する
22
+ # @rbs (String?) -> String?
23
+ # @param prefix [String, nil] 郵便番号の先頭部分(4桁以上)
24
+ # @return [String, nil] 正規化後の数字文字列。4桁未満または不正な場合は nil
25
+ def self.normalize_prefix: (String?) -> String?
26
+
27
+ # 町域文字列から「通常住所に含まれない情報」を除いた表示用文字列を返す
28
+ # 除去対象: 「以下に掲載がない場合」、全角括弧()で囲まれた部分全体
29
+ # @rbs (String?) -> String?
30
+ # @param town_str [String, nil] 町域(漢字)または町域カナ
31
+ # @return [String, nil] 除去後の文字列。nil または空になった場合は nil
32
+ def self.normalize_town_for_display: (String?) -> String?
33
+
34
+ # @rbs (String) -> String
35
+ private def self.normalize_string: (String) -> String
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ # Generated from lib/jp_address_complement/prefecture.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ # JIS X 0401 都道府県コード(01–47)⇔都道府県名の変換
5
+ module Prefecture
6
+ # JIS X 0401 都道府県コード → 都道府県名(正式名称)
7
+ CODE_TO_NAME: untyped
8
+
9
+ NAME_TO_CODE: untyped
10
+
11
+ # 都道府県コードから都道府県名を返す
12
+ # @rbs (String | Integer | nil) -> String?
13
+ # @param code [String, Integer, nil] 都道府県コード(01–47)。数値またはゼロパディング文字列
14
+ # @return [String, nil] 都道府県名。該当なし・不正入力時は nil
15
+ def self.name_from_code: (String | Integer | nil) -> String?
16
+
17
+ # 都道府県名(正式名称)から都道府県コードを2桁文字列で返す
18
+ # @rbs (String?) -> String?
19
+ # @param name [String, nil] 都道府県の正式名称
20
+ # @return [String, nil] 2桁のコード(例: "13")。該当なし時は nil
21
+ def self.code_from_name: (String?) -> String?
22
+
23
+ def self.normalize_code: (untyped code) -> untyped
24
+
25
+ def self.normalize_code_string: (untyped stripped) -> untyped
26
+ end
27
+ end
@@ -0,0 +1,8 @@
1
+ # Generated from lib/jp_address_complement/railtie.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ # Rails との統合を担う Railtie
5
+ # @rbs inherits Rails::Railtie
6
+ class Railtie < Rails::Railtie
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ # Generated from lib/jp_address_complement/repositories/active_record_postal_code_repository.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ module Repositories
5
+ # ActiveRecord を使用した PostalCodeRepository の実装
6
+ # Rails 環境向けにバンドルされる標準実装
7
+ class ActiveRecordPostalCodeRepository < PostalCodeRepository
8
+ # @rbs (String code) -> Array[AddressRecord]
9
+ # @param code [String] 正規化済み7桁郵便番号
10
+ # @return [Array<AddressRecord>]
11
+ def find_by_code: (String code) -> Array[AddressRecord]
12
+
13
+ # @rbs (String prefix) -> Array[AddressRecord]
14
+ # @param prefix [String] 4桁以上の郵便番号プレフィックス
15
+ # @return [Array<AddressRecord>]
16
+ def find_by_prefix: (String prefix) -> Array[AddressRecord]
17
+
18
+ # @rbs (pref: String?, city: String?, ?town: String?) -> Array[AddressRecord]
19
+ def find_postal_codes_by_address: (pref: String?, city: String?, ?town: String?) -> Array[AddressRecord]
20
+
21
+ private
22
+
23
+ # @rbs (pref: String?, city: String?, ?town: String?) -> untyped
24
+ def address_relation: (pref: String?, city: String?, ?town: String?) -> untyped
25
+
26
+ # @rbs () -> singleton(PostalCode)
27
+ def postal_code_model: () -> singleton(PostalCode)
28
+
29
+ # LIKE 句用に % _ \ をエスケープする
30
+ # @rbs (String) -> String
31
+ def escape_like: (String) -> String
32
+
33
+ # ActiveRecord の動的属性のため Steep の型が不足する。理由明記で抑制(research §7)
34
+ # @rbs (untyped postal_code_ar) -> AddressRecord
35
+ def to_record: (untyped postal_code_ar) -> AddressRecord
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,100 @@
1
+ # Generated from lib/jp_address_complement/repositories/csv_postal_code_repository.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ module Repositories
5
+ # UTF-8 版 KEN_ALL(utf_ken_all.csv)形式の CSV ファイルを直接読み込んで検索を行う Repository 実装
6
+ #
7
+ # - ActiveRecord や DB に依存せず、純粋に CSV から AddressRecord を構築する
8
+ # - 初回アクセス時に CSV 全体を読み込み、インメモリでインデックスを構築する(2回目以降はメモリ検索のみ)
9
+ # - CSV は日本郵便公式の KEN_ALL.CSV(UTF-8 版 utf_ken_all.csv)と同じ列構成を前提とする
10
+ #
11
+ # 典型的な利用例:
12
+ #
13
+ # require 'jp_address_complement/repositories/csv_postal_code_repository'
14
+ #
15
+ # JpAddressComplement.configure do |c|
16
+ # c.repository = JpAddressComplement::Repositories::CsvPostalCodeRepository.new('/path/to/utf_ken_all.csv')
17
+ # end
18
+ class CsvPostalCodeRepository < PostalCodeRepository
19
+ # 列インデックス(KEN_ALL.CSV 形式)
20
+ COL_PREF_CODE: ::Integer
21
+
22
+ COL_POSTAL_CODE: ::Integer
23
+
24
+ COL_KANA_PREF: ::Integer
25
+
26
+ COL_KANA_CITY: ::Integer
27
+
28
+ COL_KANA_TOWN: ::Integer
29
+
30
+ COL_PREF: ::Integer
31
+
32
+ COL_CITY: ::Integer
33
+
34
+ COL_TOWN: ::Integer
35
+
36
+ COL_IS_PARTIAL: ::Integer
37
+
38
+ COL_HAS_ALIAS: ::Integer
39
+
40
+ COL_IS_LARGE_OFFICE: ::Integer
41
+
42
+ # @rbs (String csv_path) -> void
43
+ # @param csv_path [String] 読み込む KEN_ALL 形式 UTF-8 CSV のパス
44
+ def initialize: (String csv_path) -> void
45
+
46
+ # @rbs (String code) -> Array[AddressRecord]
47
+ def find_by_code: (String code) -> Array[AddressRecord]
48
+
49
+ # @rbs (String prefix) -> Array[AddressRecord]
50
+ def find_by_prefix: (String prefix) -> Array[AddressRecord]
51
+
52
+ # @rbs (pref: String?, city: String?, ?town: String?) -> Array[AddressRecord]
53
+ def find_postal_codes_by_address: (pref: String?, city: String?, ?town: String?) -> Array[AddressRecord]
54
+
55
+ private
56
+
57
+ # @rbs () -> void
58
+ def ensure_loaded: () -> void
59
+
60
+ # @rbs () -> void
61
+ def load_csv: () -> void
62
+
63
+ # @rbs () -> void
64
+ def validate_csv_path!: () -> void
65
+
66
+ # @rbs () { (Array[String?]) -> void } -> void
67
+ def each_csv_row: () { (Array[String?]) -> void } -> void
68
+
69
+ # @rbs (Array[String?] row) -> void
70
+ def append_record: (Array[String?] row) -> void
71
+
72
+ # @rbs (AddressRecord record, String pref, String city, String? town_query) -> bool
73
+ def address_match?: (AddressRecord record, String pref, String city, String? town_query) -> bool
74
+
75
+ # @rbs (Array[String?] row) -> (AddressRecord | nil)
76
+ def build_record_from_row: (Array[String?] row) -> (AddressRecord | nil)
77
+
78
+ # @rbs (Array[String?] row) -> (Hash[Symbol, untyped] | nil)
79
+ def parse_row_attrs: (Array[String?] row) -> (Hash[Symbol, untyped] | nil)
80
+
81
+ # @rbs (Array[String?] row) -> (Array[String] | nil)
82
+ def extract_required_fields: (Array[String?] row) -> (Array[String] | nil)
83
+
84
+ # @rbs (String? cell) -> (String | nil)
85
+ def strip_cell: (String? cell) -> (String | nil)
86
+
87
+ # @rbs (String? postal_code) -> bool
88
+ def valid_postal_code_format?: (String? postal_code) -> bool
89
+
90
+ # @rbs (Array[String?], String, String, String, String) -> Hash[Symbol, untyped]
91
+ def build_row_attrs: (Array[String?], String, String, String, String) -> Hash[Symbol, untyped]
92
+
93
+ # @rbs (String? cell) -> bool
94
+ def flag?: (String? cell) -> bool
95
+
96
+ # @rbs (untyped value) -> bool
97
+ def blank?: (untyped value) -> bool
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,29 @@
1
+ # Generated from lib/jp_address_complement/repositories/postal_code_repository.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ module Repositories
5
+ # データアクセスを抽象化するインターフェース基底クラス
6
+ # 具体的な実装は ActiveRecordPostalCodeRepository またはユーザー定義アダプターで行う
7
+ class PostalCodeRepository
8
+ # 7桁郵便番号で完全一致検索する
9
+ # @rbs (String code) -> Array[AddressRecord]
10
+ # @param code [String] 正規化済み7桁郵便番号
11
+ # @return [Array<AddressRecord>]
12
+ def find_by_code: (String code) -> Array[AddressRecord]
13
+
14
+ # 郵便番号プレフィックスで前方一致検索する
15
+ # @rbs (String prefix) -> Array[AddressRecord]
16
+ # @param prefix [String] 4桁以上の郵便番号プレフィックス
17
+ # @return [Array<AddressRecord>]
18
+ def find_by_prefix: (String prefix) -> Array[AddressRecord]
19
+
20
+ # 都道府県・市区町村・町域で検索する(逆引き)。町域は前方一致。
21
+ # @rbs (pref: String?, city: String?, ?town: String?) -> Array[AddressRecord]
22
+ # @param pref [String] 都道府県名(正式名称)
23
+ # @param city [String] 市区町村名
24
+ # @param town [String, nil] 町域名。省略時は都道府県+市区町村のみ。指定時は前方一致で候補を返す
25
+ # @return [Array<AddressRecord>] 該当レコードの配列。該当なし・入力不十分時は []
26
+ def find_postal_codes_by_address: (pref: String?, city: String?, ?town: String?) -> Array[AddressRecord]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ # Generated from lib/jp_address_complement/searcher.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ # コア検索ロジック
5
+ # Repository を注入して使用することで ActiveRecord への直接依存を排除する
6
+ class Searcher
7
+ # @rbs (Repositories::PostalCodeRepository repository) -> void
8
+ def initialize: (Repositories::PostalCodeRepository repository) -> void
9
+
10
+ # 7桁郵便番号から住所レコードを検索する
11
+ # @rbs (String? code) -> Array[AddressRecord]
12
+ # @param code [String, nil] 郵便番号
13
+ # @return [Array<AddressRecord>]
14
+ def search_by_postal_code: (String? code) -> Array[AddressRecord]
15
+
16
+ # 郵便番号プレフィックスから住所候補を検索する(4桁以上)
17
+ # @rbs (String? prefix) -> Array[AddressRecord]
18
+ # @param prefix [String, nil] 郵便番号の先頭部分
19
+ # @return [Array<AddressRecord>]
20
+ def search_by_postal_code_prefix: (String? prefix) -> Array[AddressRecord]
21
+
22
+ # 郵便番号と住所文字列の整合性を検証する
23
+ # 日本郵便の utf_ken_all.csv は町域に「字」「大字」を含まないため、
24
+ # 市区町村の直後に「字」「大字」が付いた住所(省略可能な表記)も一致とみなす。
25
+ # @rbs (String? postal_code, String? address) -> bool
26
+ # @param postal_code [String, nil] 郵便番号
27
+ # @param address [String, nil] 住所文字列
28
+ # @return [Boolean]
29
+ def valid_combination?: (String? postal_code, String? address) -> bool
30
+
31
+ # 都道府県・市区町村・町域から郵便番号候補を取得する(逆引き)。町域は前方一致。
32
+ # @rbs (pref: String?, city: String?, ?town: String?) -> Array[[String, AddressRecord]]
33
+ # @param pref [String] 都道府県名(正式名称)
34
+ # @param city [String] 市区町村名
35
+ # @param town [String, nil] 町域名。省略時は都道府県+市区町村のみ。指定時は前方一致で候補を返す
36
+ # @return [Array<[String, AddressRecord]>] [郵便番号, AddressRecord] の配列。該当なし・入力不十分時は []
37
+ def search_postal_codes_by_address: (pref: String?, city: String?, ?town: String?) -> Array[[ String, AddressRecord ]]
38
+
39
+ private
40
+
41
+ def address_matches_record?: (untyped address, untyped record) -> untyped
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ # Generated from lib/jp_address_complement/validators/address_validator.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ # ActiveModel::Validator を継承した郵便番号・住所整合性バリデーター
5
+ #
6
+ # @example
7
+ # class User
8
+ # include ActiveModel::Validations
9
+ # validates_with JpAddressComplement::AddressValidator,
10
+ # postal_code_field: :postal_code,
11
+ # address_field: :full_address
12
+ # end
13
+ # @rbs inherits ActiveModel::Validator
14
+ class AddressValidator < ActiveModel::Validator
15
+ # @rbs (untyped record) -> void
16
+ def validate: (untyped record) -> void
17
+
18
+ private
19
+
20
+ def postal_code_field: () -> untyped
21
+
22
+ def address_field: () -> untyped
23
+ end
24
+ end
@@ -0,0 +1,5 @@
1
+ # Generated from lib/jp_address_complement/version.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ VERSION: String
5
+ end
@@ -0,0 +1,84 @@
1
+ # Generated from lib/jp_address_complement.rb with RBS::Inline
2
+
3
+ module JpAddressComplement
4
+ class Error < StandardError
5
+ end
6
+
7
+ class ImportError < Error
8
+ end
9
+
10
+ # Gem の設定を行う
11
+ # @rbs () { (Configuration) -> void } -> void
12
+ # @yield [Configuration]
13
+ def self.configure: () { (Configuration) -> void } -> void
14
+
15
+ # 現在の設定を返す
16
+ # @rbs () -> Configuration
17
+ # @return [Configuration]
18
+ def self.configuration: () -> Configuration
19
+
20
+ # PostalCode モデルの継承元。未設定時は ActiveRecord::Base。configuration.postal_code_model_base に委譲する。
21
+ # @rbs () -> Class
22
+ def self.base_record_class: () -> Class
23
+
24
+ # @rbs (Class) -> void
25
+ def self.base_record_class=: (Class) -> void
26
+
27
+ # PostalCode が参照するテーブル名。未設定時は 'jp_address_complement_postal_codes'。configuration.postal_code_table_name に委譲。
28
+ # @rbs () -> String
29
+ def self.postal_code_table_name: () -> String
30
+
31
+ # @rbs (String) -> void
32
+ def self.postal_code_table_name=: (String) -> void
33
+
34
+ # 設定をリセットする(主にテスト用)
35
+ # @rbs () -> void
36
+ def self.reset_configuration!: () -> void
37
+
38
+ # 設定されたリポジトリを返す(デフォルトは ActiveRecord 実装)
39
+ # @rbs () -> Repositories::PostalCodeRepository
40
+ # @return [Repositories::PostalCodeRepository]
41
+ def self.repository: () -> Repositories::PostalCodeRepository
42
+
43
+ # 7桁郵便番号から住所レコードを検索する
44
+ # @rbs (String) -> Array[AddressRecord]
45
+ # @param code [String] 郵便番号(ハイフン・全角・〒 記号を自動正規化)
46
+ # @return [Array<AddressRecord>]
47
+ def self.search_by_postal_code: (String) -> Array[AddressRecord]
48
+
49
+ # 郵便番号の先頭4桁以上から住所候補を検索する
50
+ # @rbs (String) -> Array[AddressRecord]
51
+ # @param prefix [String] 郵便番号の先頭部分(4桁以上)
52
+ # @return [Array<AddressRecord>]
53
+ def self.search_by_postal_code_prefix: (String) -> Array[AddressRecord]
54
+
55
+ # 郵便番号と住所文字列の整合性を検証する
56
+ # @rbs (String, String) -> bool
57
+ # @param postal_code [String] 郵便番号(自動正規化)
58
+ # @param address [String] 住所文字列
59
+ # @return [Boolean]
60
+ def self.valid_combination?: (String, String) -> bool
61
+
62
+ # 都道府県コード(JIS X 0401)から都道府県名を返す
63
+ # @rbs (String | Integer?) -> String?
64
+ # @param code [String, Integer, nil] 都道府県コード(01–47)
65
+ # @return [String, nil] 都道府県名。該当なし時は nil
66
+ def self.prefecture_name_from_code: (String | Integer?) -> String?
67
+
68
+ # 都道府県名(正式名称)から都道府県コードを2桁文字列で返す
69
+ # @rbs (String?) -> String?
70
+ # @param name [String, nil] 都道府県の正式名称
71
+ # @return [String, nil] 2桁のコード(例: "13")。該当なし時は nil
72
+ def self.prefecture_code_from_name: (String?) -> String?
73
+
74
+ # 都道府県・市区町村・町域から郵便番号候補を取得する(逆引き)。町域は前方一致。
75
+ # @rbs (pref: String?, city: String?, ?town: String?) -> Array[[String, AddressRecord]]
76
+ # @param pref [String] 都道府県名(正式名称)
77
+ # @param city [String] 市区町村名
78
+ # @param town [String, nil] 町域名。省略可。指定時は前方一致で候補を返す
79
+ # @return [Array<[String, AddressRecord]>] [郵便番号, AddressRecord] の配列。該当なし・入力不十分時は []
80
+ def self.search_postal_codes_by_address: (pref: String?, city: String?, ?town: String?) -> Array[[ String, AddressRecord ]]
81
+
82
+ # @rbs () -> Repositories::ActiveRecordPostalCodeRepository
83
+ private def self.default_repository: () -> Repositories::ActiveRecordPostalCodeRepository
84
+ end
@@ -0,0 +1,40 @@
1
+ # sig/manual/address_record.rbs — AddressRecord (Data.define) の手動型定義
2
+ # contracts/rbs-public-api.md, data-model.md に準拠。rbs-inline では上書きしない。
3
+
4
+ module JpAddressComplement
5
+ ADDRESS_RECORD_ATTRIBUTES: Array[Symbol]
6
+
7
+ class AddressRecord
8
+ attr_reader postal_code: String
9
+ attr_reader pref_code: String
10
+ attr_reader pref: String
11
+ attr_reader city: String
12
+ attr_reader town: String?
13
+ attr_reader kana_pref: String?
14
+ attr_reader kana_city: String?
15
+ attr_reader kana_town: String?
16
+ attr_reader has_alias: bool
17
+ attr_reader is_partial: bool
18
+ attr_reader is_large_office: bool
19
+
20
+ def initialize: (
21
+ postal_code: String,
22
+ pref_code: String,
23
+ pref: String,
24
+ city: String,
25
+ ?town: String?,
26
+ ?kana_pref: String?,
27
+ ?kana_city: String?,
28
+ ?kana_town: String?,
29
+ ?has_alias: bool,
30
+ ?is_partial: bool,
31
+ ?is_large_office: bool
32
+ ) -> void
33
+
34
+ # 通常住所に含まれない情報を除いた町域名(丁目・番地・その他等の括弧、「以下に掲載がない場合」を除去)
35
+ def normalized_town: () -> String?
36
+
37
+ # 通常住所に含まれない情報を除いた町域カナ
38
+ def normalized_kana_town: () -> String?
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ # rubyzip の Steep 用スタブ(Zip::File 等)
2
+ module Zip
3
+ class Error < StandardError
4
+ end
5
+
6
+ class File
7
+ def self.open: (String path) { (Zip::File) -> untyped } -> untyped
8
+
9
+ def each: () { (Zip::Entry) -> void } -> void
10
+ end
11
+
12
+ class Entry
13
+ attr_reader name: String
14
+
15
+ def extract: (String dest) { (bool) -> void } -> void
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # sig/manual/postal_code.rbs — PostalCode の手動型定義
2
+ # 継承元は JpAddressComplement.base_record_class(= configuration.postal_code_model_base、未設定時は ActiveRecord::Base)。型上は ActiveRecord::Base の子として扱う。
3
+
4
+ module JpAddressComplement
5
+ class PostalCode < ActiveRecord::Base
6
+ def self.where: (*untyped) -> untyped
7
+ def self.maximum: (Symbol column) -> Integer?
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class CSV
2
+ class InvalidEncodingError < StandardError
3
+ end
4
+ end
5
+