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
data/README.md ADDED
@@ -0,0 +1,274 @@
1
+ # JpAddressComplement
2
+
3
+ 日本郵便の郵便番号データ(KEN_ALL 形式、UTF-8 版 utf_ken_all.csv)を用いて、Rails アプリで住所の補完・検索・検証を行うための gem です。
4
+
5
+ ## 特徴
6
+
7
+ - **自前の RDB に住所情報を登録し、それを利用する**
8
+ 外部 API や別サービスに問い合わせるのではなく、アプリのデータベース内に郵便番号・住所データを保持し、そのテーブルに対して検索・検証を行います。
9
+
10
+ - **運用時に外部サービスに依存しない**
11
+ 住所補完や検証はすべて自前 DB に対して行うため、外部 API の障害・レート制限・仕様変更の影響を受けず、オフライン環境でも利用できます。
12
+
13
+ - **RDB のリレーションを活用できる**
14
+ 郵便番号テーブルを自前で持つため、都道府県コードや市区町村名で他のテーブルと JOIN したり、アプリ固有のマスタと組み合わせたりしやすい設計です。
15
+
16
+ - **CSV を直接利用する方式も選べる**
17
+ データベースを使わず、ローカルに配置した KEN_ALL 形式の UTF-8 CSV(`utf_ken_all.csv`)をそのまま読み込んで検索する `CsvPostalCodeRepository` も利用できます。CSV のパスは設定で指定できます。
18
+
19
+ ### 主な機能
20
+
21
+ - **郵便番号から住所を検索**(7桁完全一致・先頭4桁以上のプレフィックス検索)
22
+ - **住所から郵便番号の逆引き**
23
+ - **郵便番号と住所文字列の整合性検証**(フォーム用バリデーション)
24
+ - **都道府県コード(JIS X 0401)と都道府県名の相互変換**
25
+
26
+ ## 必要環境
27
+
28
+ - Ruby 3.2 以上
29
+ - Rails 7.1 以上
30
+ - ActiveRecord 利用を前提としています
31
+
32
+ ## インストール
33
+
34
+ ### 1. Gem の追加
35
+
36
+ アプリの `Gemfile` に追加して `bundle install` します。
37
+
38
+ ```ruby
39
+ gem 'jp_address_complement'
40
+ ```
41
+
42
+ Bundler を使わない場合:
43
+
44
+ ```bash
45
+ gem install jp_address_complement
46
+ ```
47
+
48
+ ### 2. テーブルの作成
49
+
50
+ 郵便番号データを格納するマイグレーションを生成し、マイグレートします。
51
+
52
+ ```bash
53
+ rails g jp_address_complement:install
54
+ rails db:migrate
55
+ ```
56
+
57
+ ### 3. 住所データのインポート
58
+
59
+ 日本郵便の KEN_ALL 形式 CSV(UTF-8 版 `utf_ken_all.csv`)をインポートする必要があります。
60
+
61
+ **方法A: 公式サイトから UTF-8 版を自動ダウンロードしてインポート**
62
+
63
+ ```bash
64
+ DOWNLOAD=1 rake jp_address_complement:import
65
+ ```
66
+
67
+ **方法B: 手元の UTF-8 CSV ファイルを指定してインポート**
68
+
69
+ [郵便番号データダウンロード](https://www.post.japanpost.jp/zipcode/dl/utf-zip.html) から UTF-8 版の `utf_ken_all.zip` を取得し、展開した `utf_ken_all.csv` のパスを指定します。
70
+
71
+ ```bash
72
+ CSV=/path/to/utf_ken_all.csv rake jp_address_complement:import
73
+ ```
74
+
75
+ インポートには数分かかる場合があります。完了後、`jp_address_complement_postal_codes` テーブルにデータが入っている状態になります。
76
+
77
+ ---
78
+
79
+ ## 利用方法
80
+
81
+ ### 郵便番号から住所を検索(7桁完全一致)
82
+
83
+ ```ruby
84
+ # 郵便番号はハイフン・全角・〒記号があっても自動で正規化されます
85
+ records = JpAddressComplement.search_by_postal_code('1000001')
86
+ # => [#<Data AddressRecord ...>, ...]
87
+
88
+ records.each do |r|
89
+ puts "#{r.pref} #{r.city} #{r.town}" # 例: 東京都 千代田区 千代田
90
+ puts r.postal_code # "1000001"
91
+ puts r.pref_code # "13" (JIS都道府県コード)
92
+ end
93
+ ```
94
+
95
+ ### 町域の表示用文字列(括弧等を除く)
96
+
97
+ 郵便番号データの町域(`town` / `kana_town`)には、「大通西(1〜19丁目)」「常盤(その他)」「以下に掲載がない場合」のように、通常の住所表記には含まれない括弧付きの情報などが含まれる場合があります。フォームの候補表示やラベル用に「住所としてそのまま使える町域名」だけ欲しいときは、`normalized_town` と `normalized_kana_town` を使ってください。
98
+
99
+ - **除去されるもの**: 全角括弧()で囲まれた部分全体、「以下に掲載がない場合」およびそのカナ表記
100
+ - 元の `town` / `kana_town` が `nil` のとき、または除去後に空になる場合は `nil` を返します。
101
+
102
+ ```ruby
103
+ records = JpAddressComplement.search_by_postal_code('0600042')
104
+ records.each do |r|
105
+ # 括弧付きの生データ
106
+ r.town # => "大通西(1〜19丁目)"
107
+ r.kana_town # => "オオドオリニシ(1〜19チョウメ)"
108
+
109
+ # 表示用(括弧・「以下に掲載がない場合」等を除いた町域名)
110
+ r.normalized_town # => "大通西"
111
+ r.normalized_kana_town # => "オオドオリニシ"
112
+
113
+ puts "#{r.pref} #{r.city} #{r.normalized_town}" # 例: 北海道 札幌市中央区 大通西
114
+ end
115
+ ```
116
+
117
+ ### 郵便番号のプレフィックス検索(4桁以上)
118
+
119
+ 入力中の郵便番号の先頭から候補を絞り込むときに使えます。
120
+
121
+ ```ruby
122
+ records = JpAddressComplement.search_by_postal_code_prefix('1000')
123
+ # 先頭が "1000" で始まる郵便番号の住所レコードの配列
124
+ ```
125
+
126
+ ### 郵便番号と住所の整合性チェック
127
+
128
+ 「この郵便番号とこの住所の組み合わせは正しいか?」を判定します。フォームのバリデーションに利用できます。
129
+
130
+ ```ruby
131
+ JpAddressComplement.valid_combination?('1000001', '東京都千代田区千代田')
132
+ # => true
133
+
134
+ JpAddressComplement.valid_combination?('1000001', '大阪府大阪市北区')
135
+ # => false
136
+ ```
137
+
138
+ **注意**: 複数の郵便番号で丁目や番地のみ違う町域が存在する場合や、記載以外のその他の町域となっている郵便番号は、異なる町域や丁目、番地の郵便番号でも正しいと判定される場合があります。
139
+
140
+ ### モデルでのバリデーション(AddressValidator)
141
+
142
+ `ActiveModel::Validations` と組み合わせて、郵便番号と住所フィールドの組み合わせを検証できます。
143
+
144
+ ```ruby
145
+ class Order
146
+ include ActiveModel::Model
147
+ include ActiveModel::Validations
148
+
149
+ attr_accessor :postal_code, :address
150
+
151
+ validates :postal_code, presence: true
152
+ validates :address, presence: true
153
+ validates_with JpAddressComplement::AddressValidator,
154
+ postal_code_field: :postal_code,
155
+ address_field: :address
156
+ end
157
+ ```
158
+
159
+ `postal_code_field` / `address_field` を省略すると、それぞれ `:postal_code` / `:address` が使われます。
160
+
161
+ ### 都道府県コードと都道府県名の変換
162
+
163
+ JIS X 0401 の都道府県コード(01〜47)と都道府県名の相互変換ができます。
164
+
165
+ ```ruby
166
+ JpAddressComplement.prefecture_name_from_code(13)
167
+ # => "東京都"
168
+ JpAddressComplement.prefecture_name_from_code('13')
169
+ # => "東京都"
170
+
171
+ JpAddressComplement.prefecture_code_from_name('東京都')
172
+ # => "13"
173
+ ```
174
+
175
+ ### 住所から郵便番号を逆引き
176
+
177
+ 都道府県・市区町村・町域を指定して、対応する郵便番号の一覧を取得します。
178
+
179
+ ```ruby
180
+ codes = JpAddressComplement.search_postal_codes_by_address(
181
+ pref: '東京都',
182
+ city: '千代田区',
183
+ town: '千代田'
184
+ )
185
+ # => ["1000001"] など、該当する郵便番号の配列
186
+ ```
187
+
188
+ `town` は省略可能です。その場合は都道府県+市区町村で検索されます。
189
+
190
+ ### 設定のカスタマイズ(任意)
191
+
192
+ リポジトリ(データ取得の実装)を差し替えたい場合は、Rails の初期化処理などで設定できます。
193
+
194
+ ```ruby
195
+ # config/initializers/jp_address_complement.rb
196
+ JpAddressComplement.configure do |config|
197
+ config.repository = MyApp::CustomPostalCodeRepository.new
198
+ # PostalCode モデルの継承元(未設定時は ActiveRecord::Base)
199
+ config.postal_code_model_base = ApplicationRecord
200
+ # 郵便番号テーブル名(未設定時は 'jp_address_complement_postal_codes')。マイグレーションで別名のテーブルを作った場合に指定
201
+ config.postal_code_table_name = 'my_postal_codes'
202
+ end
203
+ ```
204
+
205
+ ### CSV をローカルに配置して利用する(DB を使わない場合)
206
+
207
+ RDB やマイグレーションを使わず、KEN_ALL 形式(UTF-8 版 `utf_ken_all.csv`)の CSV をローカルに置いたまま検索だけ行いたい場合は、`CsvPostalCodeRepository` を使います。CSV のパスは任意に指定できます。
208
+
209
+ ```ruby
210
+ require 'jp_address_complement'
211
+ require 'jp_address_complement/repositories/csv_postal_code_repository'
212
+
213
+ # CSV ファイルのパスを設定して Repository を差し替える
214
+ JpAddressComplement.configure do |config|
215
+ config.repository = JpAddressComplement::Repositories::CsvPostalCodeRepository.new(
216
+ '/path/to/utf_ken_all.csv' # 任意のパスを指定可能(UTF-8 版)
217
+ )
218
+ end
219
+
220
+ # 以降は search_by_postal_code など、既存の API をそのまま利用できる
221
+ records = JpAddressComplement.search_by_postal_code('1000001')
222
+ ```
223
+
224
+ - 初回の検索時に CSV を読み込み、メモリ上にインデックスを構築します(2回目以降はメモリ検索のみ)。
225
+ - CSV は日本郵便の KEN_ALL 形式と同じ列構成を前提とし、UTF-8 版 `utf_ken_all.csv` を想定しています。
226
+
227
+ ---
228
+
229
+ ## Development
230
+
231
+ リポジトリをクローンしたあと、`bin/setup` で依存関係を入れます。`bin/console` で対話的にコードを試せます。
232
+
233
+ ### 型チェック(RBS / Steep)
234
+
235
+ 本 gem は [RBS](https://github.com/ruby/rbs) と [Steep](https://github.com/soutaro/steep) で静的型チェックを行っています。
236
+
237
+ ```bash
238
+ bundle install
239
+ bundle exec rbs collection install # 任意: サードパーティ RBS のインストール
240
+ bundle exec rake rbs:generate # sig/ を rbs-inline から生成
241
+ bundle exec rake steep # 型チェック(CI では exit 0 が必須)
242
+ ```
243
+
244
+ ### RuboCop / RSpec
245
+
246
+ コードスタイルのチェックとテストの実行は次のとおりです。
247
+
248
+ ```bash
249
+ bundle exec rubocop
250
+ bundle exec rspec
251
+ ```
252
+
253
+ 詳細は [specs/002-rbs-type-annotations/quickstart.md](specs/002-rbs-type-annotations/quickstart.md) を参照してください。
254
+
255
+ ローカルに gem をインストールするには `bundle exec rake install` を実行します。
256
+
257
+ ### リリース(RubyGems への公開)
258
+
259
+ 1. `lib/jp_address_complement/version.rb` のバージョン(例: `1.0.0`)を更新してコミット・push する。
260
+ 2. `v1.0.0` のように **v + バージョン** のタグを push する。
261
+
262
+ ```bash
263
+ git tag v1.0.0
264
+ git push origin v1.0.0
265
+ ```
266
+
267
+ 3. GitHub Actions の [Release to RubyGems](.github/workflows/release.yml) ワークフローが動き、[RubyGems.org](https://rubygems.org) に自動で公開される。
268
+
269
+ **事前準備(リポジトリのオーナー/管理者向け):**
270
+ [RubyGems.org の Trusted Publisher](https://guides.rubygems.org/trusted-publishing/adding-a-publisher/) を設定する。手順: [RubyGems.org のプロフィール](https://rubygems.org/profile/me) → 対象の gem → **Trusted publishers** → **Create** で、リポジトリオーナー・リポジトリ名・ワークフロー名(`release.yml`)を登録する。API キーや GitHub Secrets は不要。
271
+
272
+ ## Contributing
273
+
274
+ バグ報告やプルリクエストは [GitHub のリポジトリ](https://github.com/naokirin/jp_address_complement) で歓迎しています。
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ load 'lib/tasks/jp_address_complement.rake'
5
+ task default: %i[]
6
+
7
+ # RBS 型定義の生成(research.md §5, FR-005)
8
+ # steep/rbs:generate は Rails 不要のため :environment 依存にしない(Rails/RakeEnvironment 除外理由)
9
+ namespace :rbs do
10
+ desc 'rbs-inline で sig/ を生成する'
11
+ task generate: [] do
12
+ sh 'bundle exec rbs-inline --output sig/ lib/'
13
+ end
14
+ end
15
+
16
+ # 型チェック(research.md §5, FR-006)
17
+ task steep: [] do
18
+ sh 'bundle exec steep check'
19
+ end
data/Steepfile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Steep configuration for jp_address_complement (research.md §2, plan.md)
4
+ # signature "sig" includes sig/*.rbs, sig/jp_address_complement/**/*.rbs, sig/manual/*.rbs
5
+ # Rails/ActiveRecord types from rbs-rails and gem_rbs_collection
6
+ target :lib do
7
+ signature 'sig'
8
+ check 'lib'
9
+ end
@@ -0,0 +1,15 @@
1
+ # Rails credentials (master key must not be committed)
2
+ config/master.key
3
+
4
+ # sqlite database
5
+ storage/*.sqlite3*
6
+
7
+ # log files
8
+ log/
9
+ !log/.keep
10
+
11
+ # temporary backup (e.g. moved during git history rewrite)
12
+ .backup/
13
+
14
+ # temporary files
15
+ tmp/*
@@ -0,0 +1,22 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
4
+ gem "rails", "~> 8.1.2"
5
+ # Use sqlite3 as the database for Active Record
6
+ gem "sqlite3", ">= 2.1"
7
+ # Use the Puma web server [https://github.com/puma/puma]
8
+ gem "puma", ">= 5.0"
9
+
10
+ # OpenSSL 3.6.0 での CRL チェックエラー回避(openssl gem 3.1.2+ で CRL がデフォルト無効に)
11
+ gem "openssl", ">= 3.3.1"
12
+
13
+ # 郵便番号→住所検索(親リポジトリの gem を参照)
14
+ gem "jp_address_complement", path: "../../../"
15
+
16
+ # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
17
+ gem "tzinfo-data", platforms: %i[ windows jruby ]
18
+
19
+ group :development, :test do
20
+ # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
21
+ gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
22
+ end
@@ -0,0 +1,252 @@
1
+ PATH
2
+ remote: ../../..
3
+ specs:
4
+ jp_address_complement (0.1.0)
5
+ activerecord (>= 7.0)
6
+ csv (>= 3.0)
7
+ railties (>= 7.0)
8
+ rubyzip (>= 2.3)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ action_text-trix (2.1.16)
14
+ railties
15
+ actioncable (8.1.2)
16
+ actionpack (= 8.1.2)
17
+ activesupport (= 8.1.2)
18
+ nio4r (~> 2.0)
19
+ websocket-driver (>= 0.6.1)
20
+ zeitwerk (~> 2.6)
21
+ actionmailbox (8.1.2)
22
+ actionpack (= 8.1.2)
23
+ activejob (= 8.1.2)
24
+ activerecord (= 8.1.2)
25
+ activestorage (= 8.1.2)
26
+ activesupport (= 8.1.2)
27
+ mail (>= 2.8.0)
28
+ actionmailer (8.1.2)
29
+ actionpack (= 8.1.2)
30
+ actionview (= 8.1.2)
31
+ activejob (= 8.1.2)
32
+ activesupport (= 8.1.2)
33
+ mail (>= 2.8.0)
34
+ rails-dom-testing (~> 2.2)
35
+ actionpack (8.1.2)
36
+ actionview (= 8.1.2)
37
+ activesupport (= 8.1.2)
38
+ nokogiri (>= 1.8.5)
39
+ rack (>= 2.2.4)
40
+ rack-session (>= 1.0.1)
41
+ rack-test (>= 0.6.3)
42
+ rails-dom-testing (~> 2.2)
43
+ rails-html-sanitizer (~> 1.6)
44
+ useragent (~> 0.16)
45
+ actiontext (8.1.2)
46
+ action_text-trix (~> 2.1.15)
47
+ actionpack (= 8.1.2)
48
+ activerecord (= 8.1.2)
49
+ activestorage (= 8.1.2)
50
+ activesupport (= 8.1.2)
51
+ globalid (>= 0.6.0)
52
+ nokogiri (>= 1.8.5)
53
+ actionview (8.1.2)
54
+ activesupport (= 8.1.2)
55
+ builder (~> 3.1)
56
+ erubi (~> 1.11)
57
+ rails-dom-testing (~> 2.2)
58
+ rails-html-sanitizer (~> 1.6)
59
+ activejob (8.1.2)
60
+ activesupport (= 8.1.2)
61
+ globalid (>= 0.3.6)
62
+ activemodel (8.1.2)
63
+ activesupport (= 8.1.2)
64
+ activerecord (8.1.2)
65
+ activemodel (= 8.1.2)
66
+ activesupport (= 8.1.2)
67
+ timeout (>= 0.4.0)
68
+ activestorage (8.1.2)
69
+ actionpack (= 8.1.2)
70
+ activejob (= 8.1.2)
71
+ activerecord (= 8.1.2)
72
+ activesupport (= 8.1.2)
73
+ marcel (~> 1.0)
74
+ activesupport (8.1.2)
75
+ base64
76
+ bigdecimal
77
+ concurrent-ruby (~> 1.0, >= 1.3.1)
78
+ connection_pool (>= 2.2.5)
79
+ drb
80
+ i18n (>= 1.6, < 2)
81
+ json
82
+ logger (>= 1.4.2)
83
+ minitest (>= 5.1)
84
+ securerandom (>= 0.3)
85
+ tzinfo (~> 2.0, >= 2.0.5)
86
+ uri (>= 0.13.1)
87
+ base64 (0.3.0)
88
+ bigdecimal (4.0.1)
89
+ builder (3.3.0)
90
+ concurrent-ruby (1.3.6)
91
+ connection_pool (3.0.2)
92
+ crass (1.0.6)
93
+ csv (3.3.5)
94
+ date (3.5.1)
95
+ debug (1.11.1)
96
+ irb (~> 1.10)
97
+ reline (>= 0.3.8)
98
+ drb (2.2.3)
99
+ erb (6.0.1)
100
+ erubi (1.13.1)
101
+ globalid (1.3.0)
102
+ activesupport (>= 6.1)
103
+ i18n (1.14.8)
104
+ concurrent-ruby (~> 1.0)
105
+ io-console (0.8.2)
106
+ irb (1.17.0)
107
+ pp (>= 0.6.0)
108
+ prism (>= 1.3.0)
109
+ rdoc (>= 4.0.0)
110
+ reline (>= 0.4.2)
111
+ json (2.18.1)
112
+ logger (1.7.0)
113
+ loofah (2.25.0)
114
+ crass (~> 1.0.2)
115
+ nokogiri (>= 1.12.0)
116
+ mail (2.9.0)
117
+ logger
118
+ mini_mime (>= 0.1.1)
119
+ net-imap
120
+ net-pop
121
+ net-smtp
122
+ marcel (1.1.0)
123
+ mini_mime (1.1.5)
124
+ minitest (6.0.1)
125
+ prism (~> 1.5)
126
+ net-imap (0.6.3)
127
+ date
128
+ net-protocol
129
+ net-pop (0.1.2)
130
+ net-protocol
131
+ net-protocol (0.2.2)
132
+ timeout
133
+ net-smtp (0.5.1)
134
+ net-protocol
135
+ nio4r (2.7.5)
136
+ nokogiri (1.19.1-aarch64-linux-gnu)
137
+ racc (~> 1.4)
138
+ nokogiri (1.19.1-aarch64-linux-musl)
139
+ racc (~> 1.4)
140
+ nokogiri (1.19.1-arm-linux-gnu)
141
+ racc (~> 1.4)
142
+ nokogiri (1.19.1-arm-linux-musl)
143
+ racc (~> 1.4)
144
+ nokogiri (1.19.1-arm64-darwin)
145
+ racc (~> 1.4)
146
+ nokogiri (1.19.1-x86_64-darwin)
147
+ racc (~> 1.4)
148
+ nokogiri (1.19.1-x86_64-linux-gnu)
149
+ racc (~> 1.4)
150
+ nokogiri (1.19.1-x86_64-linux-musl)
151
+ racc (~> 1.4)
152
+ openssl (4.0.1)
153
+ pp (0.6.3)
154
+ prettyprint
155
+ prettyprint (0.2.0)
156
+ prism (1.9.0)
157
+ psych (5.3.1)
158
+ date
159
+ stringio
160
+ puma (7.2.0)
161
+ nio4r (~> 2.0)
162
+ racc (1.8.1)
163
+ rack (3.2.5)
164
+ rack-session (2.1.1)
165
+ base64 (>= 0.1.0)
166
+ rack (>= 3.0.0)
167
+ rack-test (2.2.0)
168
+ rack (>= 1.3)
169
+ rackup (2.3.1)
170
+ rack (>= 3)
171
+ rails (8.1.2)
172
+ actioncable (= 8.1.2)
173
+ actionmailbox (= 8.1.2)
174
+ actionmailer (= 8.1.2)
175
+ actionpack (= 8.1.2)
176
+ actiontext (= 8.1.2)
177
+ actionview (= 8.1.2)
178
+ activejob (= 8.1.2)
179
+ activemodel (= 8.1.2)
180
+ activerecord (= 8.1.2)
181
+ activestorage (= 8.1.2)
182
+ activesupport (= 8.1.2)
183
+ bundler (>= 1.15.0)
184
+ railties (= 8.1.2)
185
+ rails-dom-testing (2.3.0)
186
+ activesupport (>= 5.0.0)
187
+ minitest
188
+ nokogiri (>= 1.6)
189
+ rails-html-sanitizer (1.6.2)
190
+ loofah (~> 2.21)
191
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
192
+ railties (8.1.2)
193
+ actionpack (= 8.1.2)
194
+ activesupport (= 8.1.2)
195
+ irb (~> 1.13)
196
+ rackup (>= 1.0.0)
197
+ rake (>= 12.2)
198
+ thor (~> 1.0, >= 1.2.2)
199
+ tsort (>= 0.2)
200
+ zeitwerk (~> 2.6)
201
+ rake (13.3.1)
202
+ rdoc (7.2.0)
203
+ erb
204
+ psych (>= 4.0.0)
205
+ tsort
206
+ reline (0.6.3)
207
+ io-console (~> 0.5)
208
+ rubyzip (3.2.2)
209
+ securerandom (0.4.1)
210
+ sqlite3 (2.9.0-aarch64-linux-gnu)
211
+ sqlite3 (2.9.0-aarch64-linux-musl)
212
+ sqlite3 (2.9.0-arm-linux-gnu)
213
+ sqlite3 (2.9.0-arm-linux-musl)
214
+ sqlite3 (2.9.0-arm64-darwin)
215
+ sqlite3 (2.9.0-x86_64-darwin)
216
+ sqlite3 (2.9.0-x86_64-linux-gnu)
217
+ sqlite3 (2.9.0-x86_64-linux-musl)
218
+ stringio (3.2.0)
219
+ thor (1.5.0)
220
+ timeout (0.6.0)
221
+ tsort (0.2.0)
222
+ tzinfo (2.0.6)
223
+ concurrent-ruby (~> 1.0)
224
+ uri (1.1.1)
225
+ useragent (0.16.11)
226
+ websocket-driver (0.8.0)
227
+ base64
228
+ websocket-extensions (>= 0.1.0)
229
+ websocket-extensions (0.1.5)
230
+ zeitwerk (2.7.5)
231
+
232
+ PLATFORMS
233
+ aarch64-linux-gnu
234
+ aarch64-linux-musl
235
+ arm-linux-gnu
236
+ arm-linux-musl
237
+ arm64-darwin
238
+ x86_64-darwin
239
+ x86_64-linux-gnu
240
+ x86_64-linux-musl
241
+
242
+ DEPENDENCIES
243
+ debug
244
+ jp_address_complement!
245
+ openssl (>= 3.3.1)
246
+ puma (>= 5.0)
247
+ rails (~> 8.1.2)
248
+ sqlite3 (>= 2.1)
249
+ tzinfo-data
250
+
251
+ BUNDLED WITH
252
+ 2.6.2
@@ -0,0 +1,57 @@
1
+ # jp_address_complement デモ(Rails)
2
+
3
+ [jp_address_complement](https://github.com/naokirin/jp_address_complement) の公開インターフェースを試せるサンプル Rails アプリです。
4
+
5
+ ## 前提
6
+
7
+ - Ruby 3.2+
8
+ - 親リポジトリ(`jp_address_complement_rb`)のルートで `bundle install` 済みであること
9
+
10
+ ## セットアップ
11
+
12
+ ```bash
13
+ cd examples/rails/jp_address_complement_demo
14
+ bundle install
15
+ bin/rails db:create db:migrate db:seed
16
+ ```
17
+
18
+ ## 起動
19
+
20
+ ```bash
21
+ bin/rails server
22
+ ```
23
+
24
+ ブラウザで http://localhost:3000 を開くと、画面上部のナビから次の5つのデモを試せます。
25
+
26
+ | デモ | 対応 API | 説明 |
27
+ |------|----------|------|
28
+ | 郵便番号→住所(7桁) | `search_by_postal_code` | 7桁完全一致で住所を検索 |
29
+ | プレフィックス検索 | `search_by_postal_code_prefix` | 先頭4桁以上で候補を絞り込み |
30
+ | 整合性チェック | `valid_combination?` | 郵便番号と住所の組み合わせが正しいか判定 |
31
+ | 都道府県コード⇔名 | `prefecture_name_from_code` / `prefecture_code_from_name` | JIS都道府県コードと都道府県名の相互変換 |
32
+ | 住所→郵便番号の逆引き | `search_postal_codes_by_address` | 都道府県・市区町村・町域から郵便番号一覧を取得 |
33
+
34
+ ## サンプルデータ
35
+
36
+ `db:seed` で次の郵便番号が登録されます。
37
+
38
+ | 郵便番号 | 住所例 |
39
+ |-----------|------------------------|
40
+ | 1000001 | 東京都千代田区千代田 等 |
41
+ | 0600000 | 北海道札幌市中央区 |
42
+ | 1500002 | 東京都渋谷区渋谷 |
43
+
44
+ ## 本番用データの投入(任意)
45
+
46
+ [日本郵便の郵便番号データ](https://www.post.japanpost.jp/zipcode/download.html) から **KEN_ALL.CSV** をダウンロードし、次で一括投入できます。
47
+
48
+ ```bash
49
+ CSV=/path/to/KEN_ALL.CSV bin/rails jp_address_complement:import
50
+ ```
51
+
52
+ ## 構成
53
+
54
+ - **ルート** `/` … 各デモへのナビと郵便番号→住所(7桁)のフォーム
55
+ - **コントローラ** `AddressesController` … 各アクションで `JpAddressComplement` の API を呼び出し
56
+ - **DB** SQLite(`storage/development.sqlite3`)
57
+ - **gem** `jp_address_complement` を Gemfile の `path: "../../../"` で参照
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative "config/application"
5
+
6
+ Rails.application.load_tasks