Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

文字列による検索は項目を指定して検索する #43

Merged
merged 3 commits into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ require 'jp_prefecture'
都道府県コードを渡すと、都道府県コードから都道府県を検索します:

```ruby
pref = JpPrefecture::Prefecture.find 13
pref = JpPrefecture::Prefecture.find(13)
# => #<JpPrefecture::Prefecture:0x007fceb11927d8 @code=13, @name="東京都", @name_e="Tokyo", @name_h="とうきょうと", @name_k="トウキョウト", @zips=[1000000..2080035], @area="関東">
pref.code
# => 13
Expand All @@ -62,18 +62,27 @@ pref.type
以下のように書くことも可能です:

```ruby
JpPrefecture::Prefecture.find code: 13
JpPrefecture::Prefecture.find(code: 13)
```

### 都道府県名から都道府県を検索

前方一致で都道府県を検索します:

```ruby
JpPrefecture::Prefecture.find name: "東京都"
JpPrefecture::Prefecture.find name: "Tokyo"
JpPrefecture::Prefecture.find name: "tokyo"
JpPrefecture::Prefecture.find name: "トウキョウト"
JpPrefecture::Prefecture.find name: "とうきょうと"
JpPrefecture::Prefecture.find name: "東京"
# 漢字表記
JpPrefecture::Prefecture.find(name: "東京都")
JpPrefecture::Prefecture.find(name: "東京")

# 英語表記
JpPrefecture::Prefecture.find(name_e: "Tokyo")
JpPrefecture::Prefecture.find(name_e: "tokyo")

# ひらがな表記
JpPrefecture::Prefecture.find(name_h: "とうきょうと")

# カタカナ表記
JpPrefecture::Prefecture.find(name_k: "トウキョウト")
```

### 都道府県の一覧を取得
Expand Down Expand Up @@ -153,7 +162,7 @@ end
custom_mapping_path = "..." # /path/to/mapping_data

JpPrefecture.setup do |config|
config.mapping_data = YAML.load_file custom_mapping_path
config.mapping_data = YAML.load_file(custom_mapping_path)
end
```

Expand Down
27 changes: 18 additions & 9 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ require 'jp_prefecture'
Provide prefecture code to search prefecture's data

```ruby
pref = JpPrefecture::Prefecture.find 13
pref = JpPrefecture::Prefecture.find(13)
# => #<JpPrefecture::Prefecture:0x007fceb11927d8 @code=13, @name="東京都", @name_e="Tokyo", @name_h="とうきょうと", @name_k="トウキョウト", @zips=[1000000..2080035], @area="関東">
pref.code
# => 13
Expand All @@ -59,18 +59,27 @@ pref.type
or

```ruby
JpPrefecture::Prefecture.find code: 13
JpPrefecture::Prefecture.find(code: 13)
```

### Search by Prefecture Name

Search for a prefecture by forward match.

```ruby
JpPrefecture::Prefecture.find name: "東京都"
JpPrefecture::Prefecture.find name: "Tokyo"
JpPrefecture::Prefecture.find name: "tokyo"
JpPrefecture::Prefecture.find name: "トウキョウト"
JpPrefecture::Prefecture.find name: "とうきょうと"
JpPrefecture::Prefecture.find name: "東京"
# Kanji
JpPrefecture::Prefecture.find(name: "東京都")
JpPrefecture::Prefecture.find(name: "東京")

# English
JpPrefecture::Prefecture.find(name_e: "Tokyo")
JpPrefecture::Prefecture.find(name_e: "tokyo")

# Hiragana
JpPrefecture::Prefecture.find(name_h: "とうきょうと")

# Kakatana
JpPrefecture::Prefecture.find(name_k: "トウキョウト")
```

### All Prefectures
Expand Down Expand Up @@ -150,7 +159,7 @@ Customize mapping data with `custom_mapping_path`.
custom_mapping_path = "..." # /path/to/mapping_data

JpPrefecture.setup do |config|
config.mapping_data = YAML.load_file custom_mapping_path
config.mapping_data = YAML.load_file(custom_mapping_path)
end
```

Expand Down
104 changes: 42 additions & 62 deletions lib/jp_prefecture/prefecture.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require 'jp_prefecture/prefecture/finder'
require 'jp_prefecture/mapping'
require 'jp_prefecture/zip_mapping'

Expand Down Expand Up @@ -40,55 +41,6 @@ def self.build(code, name, name_e, name_h = nil, name_k = nil, area = nil)
pref
end

# 都道府県を検索
#
# @example
# # 都道府県コードから検索
# JpPrefecture::Prefecture.find(1)
# JpPrefecture::Prefecture.find(code: 1)
#
# # 都道府県名から検索
# JpPrefecture::Prefecture.find(name: '北海道')
#
# # 都道府県名から検索(前方一致)
# JpPrefecture::Prefecture.find(name: '東京')
#
# # 英語表記の都道府県名から検索
# JpPrefecture::Prefecture.find(name: 'Hokkaido')
# JpPrefecture::Prefecture.find(name: 'hokkaido')
#
# @param args [Integer] 都道府県コード
# @param [Hash] args 検索条件
# @option args [Integer] :code 都道府県コード
# @option args [String] :name 都道府県名/英語/ひらがな/カタカナ表記の都道府県名
# @option args [Integer] :zip 郵便番号
# @return [JpPrefecture::Prefecture] 都道府県が見つかった場合は都道府県クラス
# @return [nil] 都道府県が見つからない場合は nil
def self.find(args)
return if args.nil?

code = if args.is_a?(Integer) || args.is_a?(String)
args.to_i
else
case args.keys[0]
when :name
find_code_by_name(args[:name])
when :code
args[:code].to_i
when :zip
ZipMapping.code_for_zip(args[:zip].to_i)
end
end

names = Mapping.data[code]

return unless names

build(code,
names[:name], names[:name_e],
names[:name_h], names[:name_k], names[:area])
end

# すべての都道府県クラスを返す
#
# @example
Expand All @@ -111,23 +63,51 @@ def self.all
end
end

# 名前から都道府県コードを前方一致で検索
# 都道府県を検索
#
# 文字列は前方一致で検索する
#
# @example
# # 都道府県コードを検索
# JpPrefecture::Prefecture.find(1)
# JpPrefecture::Prefecture.find(code: 1)
#
# # 都道府県名を検索
# JpPrefecture::Prefecture.find(name: '北海道')
# JpPrefecture::Prefecture.find(name: '東京')
#
# # 英語表記の都道府県名を検索
# JpPrefecture::Prefecture.find(name_e: 'Hokkaido')
# JpPrefecture::Prefecture.find(name_e: 'hokkaido')
#
# @param name [String] 検索する都道府県名
# @return [Integer] 見つかった場合は都道府県コード
# @return [nil] 見つからない場合は nil
def self.find_code_by_name(name)
return nil if name.nil? || name.empty?
# # ひらがな表記の都道府県名を検索
# JpPrefecture::Prefecture.find(name_h: 'ほっかいどう')
#
# # カタカナ表記の都道府県名を検索
# JpPrefecture::Prefecture.find(name_k: 'ホッカイドウ')
#
# # すべての項目を検索
# JpPrefecture::Prefecture.find(all_fields: '東')
#
# @param args [Integer] 都道府県コード
# @param args [Hash<Symbol, Integer>] :code 都道府県コード
# @param args [Hash<Symbol, String>] :name 漢字表記/:name_e 英語表記/:name_h ひらがな表記/:name_k カタカナ表記
# @param args [Hash<Symbol, Integer>] :zip 郵便番号
# @param args [Hash<Symbol, (String, Integer)>] :all_fields マッピングに定義しているすべてのフィールドから検索
# @return [JpPrefecture::Prefecture] 都道府県が見つかった場合は都道府県クラス
# @return [nil] 都道府県が見つからない場合は nil
def self.find(args)
return if args.nil?

name = name.downcase
case args
when Integer, String
JpPrefecture::Prefecture::Finder.new.find(field: nil, value: args)
when Hash
search_field = args.keys.first
search_value = args.values.first

Mapping.data.each do |m|
m[1].each_value do |v|
return m[0] if v.start_with?(name)
end
JpPrefecture::Prefecture::Finder.new.find(field: search_field, value: search_value)
end

nil
end
end
end
81 changes: 81 additions & 0 deletions lib/jp_prefecture/prefecture/finder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# frozen_string_literal: true

require 'jp_prefecture/mapping'
require 'jp_prefecture/zip_mapping'

module JpPrefecture
class Prefecture
# 都道府県の検索を行うクラス
class Finder
def initialize
@mapping = Mapping.data
end

# 指定した項目を検索
#
# @param field [Symbol] 検索する項目。nil の場合は都道府県コードとして扱う
# @param value [String, Integer] 検索する内容
# @return [JpPrefecture::Prefecture] 都道府県が見つかった場合は都道府県クラス
# @return [nil] 都道府県が見つからない場合は nil
def find(field:, value:)
code = find_code(field, value)
prefecture = @mapping[code]
return unless prefecture

JpPrefecture::Prefecture.build(
code,
prefecture[:name],
prefecture[:name_e],
prefecture[:name_h],
prefecture[:name_k],
prefecture[:area]
)
end

private

# @param field [Symbol] 検索する項目
# @param value [String, Integer] 検索する内容
# @return [Integer] 見つかった場合は都道府県コード
# @return [nil] 見つからない場合は nil
def find_code(field, value)
return value.to_i if field.nil?

case field
when :all_fields
find_code_by_name_from_all_fields(value)
when :name, :name_h, :name_k, :name_e
find_code_by_name(field, value)
when :code
value.to_i
when :zip
ZipMapping.code_for_zip(value.to_i)
end
end

# すべての項目を前方一致で検索
def find_code_by_name_from_all_fields(value)
return if value.nil? || value.empty?

value = value.downcase

@mapping.each do |m|
m[1].each_value do |v|
return m[0] if v.start_with?(value)
end
end
end

# 指定した項目を前方一致で検索
def find_code_by_name(field, value)
return if value.nil? || value.empty?

value = value.downcase

@mapping.each do |m|
return m[0] if m[1][field].start_with?(value)
end
end
end
end
end
72 changes: 72 additions & 0 deletions spec/prefecture/finder_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# frozen_string_literal: true

require 'spec_helper'

describe JpPrefecture::Prefecture::Finder do
describe '#find' do
shared_examples '都道府県が見つかる' do |field, value, expected_result|
let(:result) { JpPrefecture::Prefecture::Finder.new.find(field: field, value: value) }
it { expect(result.name).to eq(expected_result) }
end

shared_examples '都道府県が見つからない' do |field, value|
let(:result) { JpPrefecture::Prefecture::Finder.new.find(field: field, value: value) }
it { expect(result).to be_nil }
end

describe 'field に all_fields (すべての項目) を指定する' do
# area の「東北」が最初にマッチする
it_behaves_like '都道府県が見つかる', :all_fields, '東', '青森県'
it_behaves_like '都道府県が見つからない', :all_fields, '饂飩'
end

describe 'field に name (漢字表記) を指定する' do
it_behaves_like '都道府県が見つかる', :name, '北海道', '北海道'
it_behaves_like '都道府県が見つかる', :name, '東京', '東京都'
it_behaves_like '都道府県が見つかる', :name, '京都', '京都府'
it_behaves_like '都道府県が見つからない', :name, '饂飩'
end

describe 'field に name_e (英語表記) を指定する' do
it_behaves_like '都道府県が見つかる', :name_e, 'HOKKAIDO', '北海道'
it_behaves_like '都道府県が見つかる', :name_e, 'Hokkaido', '北海道'
it_behaves_like '都道府県が見つかる', :name_e, 'hokkaido', '北海道'
it_behaves_like '都道府県が見つからない', :name_e, 'Udon'
end

describe 'field に name_h (ひらがな表記) を指定する' do
it_behaves_like '都道府県が見つかる', :name_h, 'ほっかいどう', '北海道'
it_behaves_like '都道府県が見つかる', :name_h, 'ほっかい', '北海道'
it_behaves_like '都道府県が見つからない', :name_h, 'うどん'
end

describe 'field に name_k (カタカナ表記) を指定する' do
it_behaves_like '都道府県が見つかる', :name_k, 'ホッカイドウ', '北海道'
it_behaves_like '都道府県が見つかる', :name_k, 'ホッカイ', '北海道'
it_behaves_like '都道府県が見つからない', :name_k, 'ウドン'
end

describe 'field に code (都道府県コード) を指定する' do
it_behaves_like '都道府県が見つかる', :code, 1, '北海道'
it_behaves_like '都道府県が見つかる', :code, '1', '北海道'
it_behaves_like '都道府県が見つかる', :code, '01', '北海道'
it_behaves_like '都道府県が見つからない', :code, 999
it_behaves_like '都道府県が見つからない', :code, '999'
end

describe 'field に zip (郵便番号) を指定する' do
it_behaves_like '都道府県が見つかる', :zip, 10_000, '北海道'
it_behaves_like '都道府県が見つかる', :zip, '010000', '北海道'
it_behaves_like '都道府県が見つからない', :zip, 999_999
it_behaves_like '都道府県が見つからない', :zip, '999999'
end

describe 'field を指定しない' do
it_behaves_like '都道府県が見つかる', nil, 1, '北海道'
it_behaves_like '都道府県が見つかる', nil, '1', '北海道'
it_behaves_like '都道府県が見つかる', nil, '01', '北海道'
it_behaves_like '都道府県が見つからない', nil, 999
it_behaves_like '都道府県が見つからない', nil, '999'
end
end
end
Loading