Rails
ken_all.csv
郵便番号データ

Railsで郵便番号一覧を加工して返却する住所検索APIを作ってみる。

07. 郵便番号一覧を加工して返却する住所検索APIを作ってみる。

この記事の続きになります。

(01〜05はこちら)
とりあえず住所検索APIサーバーをRailsで構築してみました。(住所の精度は無視しています。) - Qiita
(06はこちら)
RailsでKEN_ALL.CSVファイルを取り込む時にバルクインサートを利用して処理時間を改善する。 - Qiita

これから作成するV2バージョンのAPIでは町域について置換処理で加工したデータを返却します。

郵便番号情報を返却するための簡単なサービスクラスを作成します。

置換についての仕様です。

  • 郵便番号は全角->半角置換
  • 郵便番号は半角数値以外は削除
  • 町域名に以下の置換処理を追加します。こちらの記事を参考にしました。
    郵便番号から住所を検索するサービスにまともなものがない - ぐるぐる~

    • "以下に掲載がない場合"を削除する。
    • "〜"からはじまる以降の文字列を削除する
    • "、"からはじまる以降の文字列を削除する
    • "("からはじまる以降の文字列を削除する

町域名を加工するサービスクラス

services/yubin_service.rb
class YubinService < BaseService
  attr_reader :zipcode,
              :yubins

  def initialize(zipcode)
    @zipcode = zipcode.to_s.tr('0-9', '0-9').sub(/[^0-9]/, '')
    @yubins = Yubin.where(zipcode: @zipcode).order('street_address ASC')
  end

  private
    def perform
      @yubins.each do |yubin|
        yubin.street_address.sub!(/~.+$|(.+$|、.+$|以下に記載がない場合|^[0-90-9].+$/,'')
      end
      @yubins
    end
end

サービス基底クラス

services/base_service.rb
class BaseService
  include ActiveModel::Model

  def provide
    raise_validation_error if invalid?
    perform
  end

  private

    def perform
      raise NotImplementedError.new("You must implement #{self.class}##{__method__}")
    end

    def raise_validation_error()
      raise ActiveRecord::RecordInvalid.new(self)
    end
end

コントローラークラス

api/v2/yubin_controller.rb
module Api
  module V2
    class YubinController < ApplicationController
      def search
        @yubins = YubinService.new(params[:id]).provide
        @message = "該当の郵便番号は見つかりませんでした。" if @yubins.blank?
        @status = @yubins.blank? ? 400 : 200
      end
    end
  end
end

リクエストバージョンV1とV2の比較

v1リクエストで住所検索
$ http http://0.0.0.0:3000/api/v1/yubins/3994232
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
ETag: W/"28120c12e7f0a450c054bed0f65f937b"
Referrer-Policy: strict-origin-when-cross-origin
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-Request-Id: 165f830b-116d-46fe-a135-c601e14ec9af
X-Runtime: 0.019229
X-XSS-Protection: 1; mode=block

{
    "count": 2,
    "message": "",
    "results": [
        {
            "locality": "駒ヶ根市",
            "region": "長野県",
            "street_address": "下平(2070~2119、2309~2311、2419、2421~2426",
            "zipcode": "3994232"
        },
        {
            "locality": "駒ヶ根市",
            "region": "長野県",
            "street_address": "、2433~2450)",
            "zipcode": "3994232"
        }
    ],
    "status": 200
}
V2リクエストで住所検索
$ http http://0.0.0.0:3000/api/v2/yubins/3994232
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
ETag: W/"b65937ad761ca2c99434f8ba51f6bd33"
Referrer-Policy: strict-origin-when-cross-origin
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-Request-Id: 2f9fda59-f5e0-4c25-8a88-60d747118c3f
X-Runtime: 0.007724
X-XSS-Protection: 1; mode=block

{
    "count": 2,
    "message": "",
    "results": [
        {
            "locality": "駒ヶ根市",
            "region": "長野県",
            "street_address": "",
            "zipcode": "3994232"
        },
        {
            "locality": "駒ヶ根市",
            "region": "長野県",
            "street_address": "下平",
            "zipcode": "3994232"
        }
    ],
    "status": 200
}

street_address(町域)がスッキリですね。