Rubyのdigメソッドの便利な使い方

こんにちは!kossyです!




さて、今回はRubyのdigメソッドの便利な使い方について、
ブログに残してみたいと思います。





環境
Ruby 2.6.3
MacOS Catalina



まずはドキュメント

はい、まずはドキュメントを読んでみましょう。

Hashクラスに生えているdigメソッドのドキュメント

dig(key, ...) -> object | nil[permalink][rdoc][edit]
self 以下のネストしたオブジェクトを dig メソッドで再帰的に参照して返します。途中のオブジェクトが nil であった場合は nil を返します。

[PARAM] key:
キーを任意個指定します。
h = { foo: {bar: {baz: 1}}}

h.dig(:foo, :bar, :baz) # => 1
h.dig(:foo, :zot, :xyz) # => nil

g = { foo: [10, 11, 12] }
g.dig(:foo, 1) # => 11

出典: https://docs.ruby-lang.org/ja/latest/method/Hash/i/dig.html


Arrayクラスに生えているdigメソッドのドキュメント

dig(idx, ...) -> object | nil[permalink][rdoc][edit]
self 以下のネストしたオブジェクトを dig メソッドで再帰的に参照して返します。途中のオブジェクトが nil であった場合は nil を返します。

[PARAM] idx:
インデックスを整数で任意個指定します。
a = 1, [2, 3]

a.dig(0, 1, 1) # => 3
a.dig(1, 2, 3) # => nil
a.dig(0, 0, 0) # => TypeError: Integer does not have #dig method
[42, {foo: :bar}].dig(1, :foo) # => :bar

出典: https://docs.ruby-lang.org/ja/latest/method/Array/i/dig.html

このメソッドのキモは、「途中のオブジェクトが nil であった場合は nil を返します」ですね。


ユースケース

「渡ってくるハッシュのkeyがnilかもしれない」という場合は、digメソッドが使えるかと思います。

通常、以下のような使い方をしようとすると、NoMethodErrorエラーが発生してしまいます。

irb(main):001:0> params = {}
=> {}
irb(main):002:0> params[:articles]
=> nil
irb(main):003:0> params[:articles][:title] = "title"

NoMethodError (undefined method `[]=' for nil:NilClass)

そこで、digメソッドの出番です。

以下のようなハッシュがあった場合、

json = {
  user: {
    name: 'kossy',
    addresses: {
      city: '東京都'
     }
  }
}

other_json = { 
  user: { 
    name: 'kossy'
  }
}

other_jsonの方はaddressesキーがありませんが、
digメソッドを使えばaddressesキーを呼び出してもエラーにはなりません。

json.dig(:user, :addresses, :city)
=> "東京都"

other_json.dig(:user, :addresses, :city)
=> nil

このように、「渡ってくるハッシュのkeyがnilかもしれない」という場合は、
digメソッドが使えるかと思います。




勉強になりました。




参考にさせていただいたサイト

RailsのActiveRecordにidsメソッドが生えてた

こんにちは!kossyです!




さて、今回はActiveRecordにidsメソッドの使い方について、
ブログに残してみたいと思います。




環境
Ruby 2.6.3
Rails 6.0.3
MacOS Catalina



まずはドキュメントを見る

なにはともあれまずはAPIドキュメントをみてみます。

Pluck all the ID's for the relation using the table's primary key

Person.ids # SELECT people.id FROM people
Person.joins(:companies).ids # SELECT people.id FROM people INNER JOIN companies ON companies.person_id = people.id

# File activerecord/lib/active_record/relation/calculations.rb, line 220
def ids
pluck primary_key
end

出典: https://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-ids

pluckメソッドを利用してprimary_keyを集めた配列を返すメソッドです。

このメソッドを利用することで、

Person.pluck(:id)

と書いたところを、

Person.ids

のように書くことができます。




勉強になりました。

Railsでroutingにconstraintsメソッドで制約を与える

こんにちは!kossyです!




さて、今回はRailsでroutingにconstraintsメソッドで制約を与える方法について、
ブログに残してみたいと思います。




環境
Ruby 2.6.3
Rails 6.0.3
MacOS Cathalina



使い方

例えば、正規表現と組み合わせて、以下のように設定できます。

config/routes.rb

get 'articles/:id', to: 'articles#show', constraints: { id: /[A-Z]\d{5}/ }

こうすることにより、/articles/A89318 のようなpath以外にはマッチできないようにすることができます。
/articles/893 のようなpathにはマッチしないということです。

また、以下のように、hostの制限を加えることもできます。

config/routes.rb


constraints host: "railsguides.jp" do
  namespace :admin, path: "" do
    resource :articles
  end
end

こうすることにより、adminの中に設定されているルーティングにホスト名による制約が付与されます。
つまり、railsguides.jp というホスト名でアクセスされた場合のみ、管理者用ページが表示されるようになります。




勉強になりました。




参考にさせていただいた記事


https://y-yagi.tumblr.com/post/92386974040/rails-routing-constraints%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

人事情報をRDBで管理する場合、どの情報を元に突合を行うべきか考えてみた

こんにちは!kossyです!



さて、今回は人事情報(姓名、住所、役職、社員番号、メールアドレス、電話番号等)をRDBに格納する際、
どの情報を元に突合(存在確認)を行うべきか、考えてみたいと思います。


結論は、要件次第

はい、この結論だと記事として成立しないので、
要件次第ではあるものの、要件を列挙した上で、
思考を進めてみたいと思います。

絶対に変わらない情報を探す

これが一番安全に突合できる情報かと思います。

例えば、生年月日は絶対に変わらない情報と言えるでしょう。
生まれた日を変えることは不可能だからですね。

絶対ではないですが、マイナンバーも変わり得ることはないですね。
https://www.city.atsugi.kanagawa.jp/shiminbenri/totokezei/todokede/bangoseido/d042259.html

なので、マイナンバー + 生年月日 で 突合すれば、あらゆる要件に対応できるのかなと思います。

他には?

正直、他の情報は変わり得ます。

姓名は結婚で変わることがあるし、
性別もこのご時世、変更することもあるでしょう。
社員番号も転籍や出向で変わることがあり得ますし、
メールアドレスも電話番号も変わり得るでしょう。

なので、マイナンバー + 生年月日 の合わせ技が使えない場合は、
それぞれの要件に合わせて突合情報を工夫する必要があります。


まとめ

人事DBを扱う現場のソフトウェアはどのように突合を行っているか気になりますね。

Rubyの分割代入でワンライナーでfreeze付き定数を定義してみる

こんにちは!kossyです!




さて、今回はRubyの分割代入でワンライナーでfreeze付き定数を定義する方法について、
ブログに残してみたいと思います。



環境
Ruby 2.6.3



方法

早速コード全晒しです。

INITIAL_PLAN_PRICE, SECOND_PLAN_PRICE, THIRD_PLAN_PRICE = [1000, 2000,3000].map(&:freeze)

INITIAL_PLAN_PRICE
=> 1000

SECOND_PLAN_PRICE
=> 2000

THIRD_PLAN_PRICE
=> 3000

Rubyの分割代入機能は、配列の形で記述しても有効になります。
map(&:freeze)とすることで、全ての定数をfreezeすることが出来ます。

ちなみに、以下の書き方だとfreezeしてくれませんでした、、、

# ダメパターン1

NO_FREEZED_STR_1, NO_FREEZED_STR_2 = ["aaa", "bbb"].freeze

NO_FREEZED_STR_1.upcase!
=> "AAA"

NO_FREEZED_STR_1
=> "AAA" # 定数のはずなのに破壊的メソッドが有効、、、


# ダメパターン2
NO_FREEZED_STR_1, NO_FREEZED_STR_2 = "aaa", "bbb".freeze

NO_FREEZED_STR_1.upcase!
=> "AAA"

NO_FREEZED_STR_2.upcase!

Traceback (most recent call last):
        5: from /usr/bin/irb:23:in `<main>'
        4: from /usr/bin/irb:23:in `load'
        3: from /Library/Ruby/Gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        2: from (irb):13
        1: from (irb):13:in `upcase!'

ダメパターン2の方はそりゃそうだって感じですね、、、





勉強になりました。

RailsのActiveRecordのmergeメソッドを使ってみる

こんにちは!kossyです!





さて、今回はRailsActiveRecordのmergeメソッドを使って、
ActiveRecord Queryを組み立てる方法について、ブログに残してみたいと思います。



環境
Ruby 2.6.3
Rails 6.0.3
MacOS Catalina




前提

テーブル定義は以下とします。

・tenantsテーブル
・branchesテーブル
・usersテーブル
・daily_reportsテーブル

リレーションは以下とします。
・tenant has_many branches
・tenant has_many users
・branch has_many users
・User has_many daily_reports

カラムとして、以下を定義します。
・usersテーブルにrole(権限)カラムを定義。取りうる値は、general、hr、admin の3つとします。



mergeメソッドの基本

まずは公式APIドキュメントを見てみましょう。

Merges in the conditions from other, if other is an ActiveRecord::Relation. Returns an array representing the intersection of the resulting records with other, if other is an array.
otherがActiveRecord :: Relationの場合、otherの条件にマージします。
otherが配列の場合、結果のレコードとotherの交差を表す配列を返します。

Post.where(published: true).joins(:comments).merge( Comment.where(spam: false) )

# Performs a single join query with both where conditions.
# 両方のwhere条件で単一の結合クエリを実行します。

recent_posts = Post.order('created_at DESC').first(5)
Post.where(published: true).merge(recent_posts)

# Returns the intersection of all published posts with the 5 most recently created posts.
# 公開されたすべての投稿と最近作成された5つの投稿の共通部分を返します。

# (This is just an example. You'd probably want to do this with a single query!)
# これはほんの一例です。 あなたには、これを1つのクエリで実行することをお勧めします。

ふむふむ、「otherが配列の場合、結果のレコードとotherの交差を表す配列を返します。」が肝ですね。

「交差」なので、Rubyの条件演算子で書くと、A && B に合致するレコードが返り値になるということですね。いわゆる「積集合」です。
ちなみに「和集合」は「合併」と言われることが多いです。Ruby で表現するとしたら、A || B ですね。

TypeScriptでは「交差型(Intersection Types)」と「合併型(Union Types)」と言いますので、合併や交差という単語は一般的なんだと思われます。(間違ってたら教えてください)

前提で示したテーブル構成でmergeメソッドを役立たせるとするならば、

# Branchに所属するUserの中で、roleがhrのUserを持つBranchを取得する

$ Branch.joins(:users).merge(User.where(role: :hr)).to_sql
=>
"SELECT \"branches\".*
 FROM \"branches\"
 INNER JOIN \"users\" ON \"users\".\"branch_id\" = \"branches\".\"id\"
 WHERE \"users\".\"role\" = 1
"

みたいな感じでしょうか。



実践的な使い方

先ほど「otherが配列の場合、結果のレコードとotherの交差を表す配列を返します。」と説明しましたが、
ActiveRecordのor演算子と組み合わせることで、合併を表す配列を返すことも可能です。

# Branchに所属するUserの中で、roleがgeneralかhrのUserを持つBranchを取得する

$ Branch.joins(:users).merge(User.where(role: :hr).or(User.where(role: :general))).distinct.to_sql
=> 
"SELECT DISTINCT \"branches\".*
 FROM \"branches\"
 INNER JOIN \"users\" ON \"users\".\"branch_id\" = \"branches\".\"id\"
 WHERE (\"users\".\"role\" = 1 OR \"users\".\"role\" = 2)
"

上記のようにorメソッドを用いることで、合併の挙動を表現することができます。



以下にもう一つ例を記載します。

# 日報を持っていないUserがいるBranchを取得
$ Branch.joins(:users).merge(User.left_joins(:daily_reports).where(daily_reports: {user_id: nil})).distinct.to_sql
=>
"SELECT DISTINCT \"branches\".*
 FROM \"branches\"
 INNER JOIN \"users\" ON \"users\".\"branch_id\" = \"branches\".\"id\"
 LEFT OUTER JOIN \"daily_reports\" ON \"daily_reports\".\"user_id\" = \"users\".\"id\"
 WHERE \"daily_reports\".\"user_id\" IS NULL
"

上記のようなクエリを組み立てることで、例えば「日報を持っていないユーザーがいる支社の人事に対して、リマインドメールを送信する」みたいなことが出来ます。



mergeメソッド、うまく使えば絞り込みの挙動をより簡潔に表現できそうです。





勉強になりました。




参考にさせていただいた記事
ActiveRecord の or は merge とセットで使え - Qiita
ActiveRecord::SpawnMethods

キャッシュレス推進協議会のAPI開発原則を読んでみた

こんにちは!kossyです!




さて、今回はキャッシュレス推進協議会のAPI開発原則が
普段のAPI設計にも活かせると思ったので、ブログにて紹介できればと思います。



本記事は
https://www.paymentsjapan.or.jp/wordpress/wp-content/uploads/2019/11/API_Guideline_Ver2.0.pdf
を全面的に参考にさせていただきました。この場を借りてお礼を申し上げます。




【原則1】API 接続先目線を意識した分かりやすくシンプルな設計・記述とすること

・オープン API は、API 接続先による利用を前提とするものであり、API 接続先目線を意識したわかりやすくシンプルな設計・記述とすることが求められる。かかる設計・記述は、API 接続先側でのバグの発生リスクの抑制や複数決済事業者と接続するFinTech サービスにおける決済事業者間の仕様差異の調整の容易化、決済事業者が他の事業者等と連携する際の API の汎用性、拡張性の確保にも資する。

・決済事業者における設計・記述に当たっては、API 接続を行うことを検討しているFinTech 企業等ともよく協議・連携することが望ましい。また、API の仕様決定後は、API 接続先が関係する部分の仕様について自社特有の用語や決済業界特有の略語等を使用しない平易な解説書(仕様書)を準備する等によって、API の仕様に対する API接続先の誤解・誤認等を防止することが推奨される。

・シンプルな設計・記述とすることは、実際のサービスに必要な項目のみを抽出のうえ提供する等の対応を意味し、メッセージ上の項目数の削減のみを目的に種類・性質の異なる複数の項目を結合・統合する等の対応を意味しない。一般に、統合された項目を分離して API 接続先がシステムに取り込むよりも、分離された項目を API 接続先において統合する方が、API 接続先のシステム設計がシンプルかつ汎用性の高いものとなる。



シンプルさ、本当に大事ですよね。
パラメータ数十個も送ったりするようなインターフェイスだとバグの元ですし、実装も煩雑になると思います。

「また、API の仕様決定後は、API 接続先が関係する部分の仕様について
自社特有の用語や決済業界特有の略語等を使用しない平易な解説書(仕様書)を準備する」

も重要だと思いました。Web開発の現場だとサーバーとフロントが別チームになっていることも多く、
ある程度規模の大きい(4 ~ 5人以上)開発ならAPIドキュメントの用意は必須だと思います。


【原則2】API の種類に応じた適切なセキュリティレベルを確保すること

・決済サービスの API(以下、「決済 API」)では、決済事業者の保有する秘匿性の高い情報が提供されるため、API の種類に応じた適切なセキュリティレベルを確保することが必要である。認証方式、通信方式等を含めた、具体的なセキュリティ対策やその水準については、「3 セキュリティ対策および利用者保護対策」を参照のこと。

・セキュリティレベルを確保する上では、提供する各 API のスコープ(機能)を適切な粒度とし、API 接続先が認可された権限以上の API を使用することができないようにすることが必要である。

サイバー攻撃やサイバー犯罪の手口は年々巧妙化しているため、API のセキュリティ対策および水準は、API 接続先とも連携のうえ、継続的な改善・見直し、高度化を図っていくことが必要である。

API の仕様書を一般に公開する場合、セキュリティに及ぼす影響について留意することが必要である。



認証と認可、非常に重要ですね。

「認証は本人性を証明すること」
「認可は行為の権利を認めること」

この点を履き違えていると重大なセキュリティ事故に繋がってしまいます。
必ず理解しておくようにしましょう。

ちなみにRailsでは「認証」の仕組みを提供するGemとして「devise」が有名で、
「認可」の仕組みを提供するGemは「cancancan」や「pundit」が有名です。


【原則3】デファクトスタンダードや諸外国の API 標準、国際標準規格との整合性を意識すること

・参照可能な国際標準規格等が存在する場合は可能な限り使用することが推奨される。例えば、日付や時刻の表現形式には RFC3339 や ISO8601/JISX0301、通貨コードの表現形式には ISO4217 といった標準がある。

アーキテクチャ・スタイルやデータ表現形式、認可プロトコル等の仕様については、デファクトスタンダードや諸外国の API 標準、国際標準規格等との整合性を踏まえ、「2.3 開発標準」において推奨される基本的な仕様を定めている。



国際標準規格に従うことは地味に大事ですね、、、
規格に従わないでそれぞれが独自に開発を進めてしまうと、条件分岐が多くなったりしますので。

USBにもType-cのように規格が、電源プラグにも100ボルト2極タイプのような規格がありますが、
この規格が存在しなかった場合、各社がそれぞれ独自規格で製品を作ることによって、
互換性が無くなったり、規格がたくさん存在することで次の製品の規格をどうするか、といった余計な意思決定コストがかかること、
また消費者や開発者が困ってしまうので、プログラミングでも製品開発でも規格に従うのは非常に重要だと考えます。



【原則4】仕様変更による API 接続先への影響をコントロールすること

API の仕様変更は、API 接続先でもプログラム変更等の影響が生じることから、影響を適切にコントロールすることが必要である。決済 API は、利用者の購買行動や資産管理行動の一部として機能する可能性があるため、仕様変更によって API 接続先が突然接続不能となった場合、API 接続先のサービスを利用する多くの利用者に影響・混乱が生じるおそれがある。

・仕様変更による API 接続先への影響を抑制するため、決済 API は、予めできるだけ汎用性、拡張性の高い設計とし、また、仕様変更が発生する可能性(機能追加、停止、バグ修正、データ形式の変更等)をできるだけ予め考慮した設計とすることが望ましい。これらは、各決済事業者における API の仕様変更コストを低減することにも資する。

・一方的な仕様変更によって API 接続先に混乱が生じないよう、仕様変更に当たっては、原則として十分な余裕をもって事前のアナウンスを行うことが必要である。また、新バージョン移行後も新旧バージョンを一定期間並行稼働させる、旧仕様を包含した新バージョンをリリースする等の対応も推奨される。

・パートナー型のオープン API の場合、通常、決済事業者側から API 接続先を特定することが可能であるため、事前アナウンス等は比較的容易であるが、公開情報等をパブリック型のオープン API を通じて提供する場合等では、決済事業者側から API 接続先を特定することができない場合がある。また、パートナー型のオープン API であっても、決済事業者への通知なく API の連鎖5を許容している場合は、仕様変更の影響範囲を決済事業者側で十分把握することができない場合がある。このため、仕様変更に当たっては、影響範囲を十分慎重に見極めた上で進めることが重要である。

  • 推奨される具体的なバージョン管理の方法については、「2.3 開発標準」において定めている。

APIのバージョニング、悩ましい問題ですよね、、、
namespaceで区切る設計(api/v1/ みたいな)やホスト名にAPIバージョンを含むパターンがありますが、
一長一短だと思います。


【原則5】サービス提供までに十分な確認を行うこと

・仕様書に十分な記載が行われていたとしても、システムを稼動させることで発覚する課題等があることも想定される。そのため、実際にサービス提供を開始するまでに、決済事業者、API 接続先の双方が参加する事前の確認を十分に行う必要がある。

・上記の確認を行うための環境(テスト環境やテストデータ等)については、決済事業者側にて準備されることが望ましい。



十分な確認、頭ではわかっているんですが、なかなか実践が難しいですね、、、
専門のチームを立てた方がいいと思うのですが、資金の制約、採用の困難さ等が重なって
なかなかできないチームが多いと思います。



さすが民間団体って感じの資料ですね、、、
政府主導の資料であればこのレベルの資料は作れなかったのではないでしょうか。

他にも公表物が出ていますので、興味のある方はご覧ください。



RDBの履歴テーブルにdefault値を設定するのは避けよう

こんにちは!kossyです!



さて、今回はRDBの履歴テーブルにdefault値を設定するのは避けよう、という提言を
ブログに残してみたいと思います。


前提

読書管理アプリ見たいなものを想像してください。

読書記録の編集履歴を保存する機能があって、

reading_record
reading_record_histories

というテーブルがある想定

なぜdefault値を設定したらダメなの?

reading_recordテーブルのレコードにUPDATE文が走った場合、
UPDATEが走る前のreading_recordレコードがreading_record_historiesにinsertされるという仕様だったとします。

ここで、もしreading_recordレコードのとあるカラムがnullで、reading_record_historiesのとあるカラムにdefault値が設定されているとします。

この場合、reading_record_historiesはreading_recordのコピーレコード(主キー、created_atとかupdated_atは別)でないといけないのに、
意図しない値が入ることになります。(まぁ普通に実装してればないだろうけど、、、)

なので、「履歴テーブルにdefault値を設定するのは避けよう」という結論に至るわけです。

「普通に実装してれば」と記載しましたが、
reading_recordモデルにきちんとvalidationを貼ったり、default値を設定していれば問題ないと言うことです。




皆さんはどう考えますでしょうか。

日本の健康施策の変遷その1

こんにちは!kossyです!




さて、今回は日本の健康施策の変遷について調べてみたので、
自分なりにまとめてみようかと思います。




日本の健康施策について

明治期初期

・江戸〜明治初期頃は東洋医学に基づく漢方医が大多数で、西洋医の数は非常に少なかった
・医師やその他の医療関係者(薬剤師や助産師等)に関する資格制度が存在せず、それら医療関係者の技能も高くはなかった
・国民の衛生状態も非常に悪く、政府には、速やかに保健衛生全般に関する制度を整備することが求められていた
・日本における衛生行政は1868(明治元)年に政府が西洋医学採用の方針を発表した頃より軌道に乗り始めたとされる
・西洋医学を学び、試験に合格した者のみ医師としての開業を許可するという政策を打ち出す

参考
https://www.iken.ac.jp/column/column_28.html


明治期の感染症対策

  • 諸外国との交流の結果、コレラ菌が海外から流入
  • 明治10年代にコレラが大流行、感染拡大防止のため「「伝染病予防規則」を策定
  • 伝染病学の進歩もあり、同規則の在り方が再検討され、「伝染病予防法」の策定に至る
  • 明治中期の頃からは、都市労働者間での結核が流行
  • 結核予防に関する法令の整備に乗り出し、1904年に「肺結核予防ニ関スル件」が公布
  • その後も結核死亡者数は10万人以上で推移。1919(大正8)年には、統一的な結核予防法規の制定を望む声の高まりを受けて、「結核予防法」が制定

戦時下の衛生行政

  • 1937年4月、「保健所法」が制定され、国民一般を対象とする国の健康指導相談の機関として、保健所が設置
  • 保健所は、国民の体位を向上させるため、地方において保健上必要な指導を行う所と規定され、1937年度には全国で49か所、以後5年間で187か所が整備
  • 1938年1月、内務省から分離する形で厚生省が誕生し、以後、保健所に関する事項を含む衛生行政は、厚生省衛生局の担当に
  • 1942年、体力向上についての指示や療養に関する処置命令の権限等を保健所長に移管、結果、保健所は指導機関から行政措置を行う機関としての性格も併せ持つように
  • 1940(昭和15)年に、未成年者の体力向上と結核予防を目標とした「国民体力法」が制定
  • 満17歳以上満19歳以下の男子(1942年以降は、満25歳以下の男子)を対象に毎年体力検査が行われるように
  • 疾病異常検診として結核に重点。長期にわたって我が国の結核対策の基本となった手法であるツベルクリン反応検査・X線検査の集団検診方式が採用

戦後

・「日本国憲法」の中で、「すべて国民は、健康で文化的な最低限度の生活を営む権利を有する」ことが明記
・「国は、すべての生活部面について、社会福祉社会保障及び公衆衛生の向上及び増進に努めなければならない」とされた
=> 戦後の我が国の社会保障制度の基本的理念がはっきりと憲法に盛られた

労働関係諸立法の制定と労働省の設置

GHQ主導で労働の民主化推進、1945年に労働者の団結権、団体交渉権、争議権を保障した「労働組合法」が制定
・1947年4月には最低労働条件を定めた「労働基準法」が制定
・同年9月「労働者の福祉と職業の確保とを図り、経済の興隆と国民生活の安定とに寄与」するため、労働省が設置
労働基準法の認識に基づき、労働者に対する健康診断を使用者に義務づけ
・1972(昭和47)年に制定された「労働安全衛生法」には、感染症対策以外の健康管理を目的とした健康診断項目が随時追加され、現在の定期健康診断となっている。

成人病との闘い

・成人病対策が昭和30年代の我が国における保健医療の大きなテーマだった

当時の成人病対策

①成人病は長期間にわたる内外の諸条件の影響により起こるものであり、日常生活の環境
条件との関係に注目する必要があったことから、我が国の風土、生活習慣、産業の在り
方などのうち、どれが成人病に最も強く影響を与える因子であるのかを明らかにしなけ
ればならなかったこと

②成人病の予防、早期発見対策として、感染症の場合の予防接種や結核の集団検診とは異
なった方法を開発する必要があったこと

③がんは別として、脳血管疾患、心疾患は、一応症状が安定してしまうと、慢性患者とし
て放置され、徐々に衰えていくという経過をたどりがちであったため、家庭や社会にお
ける患者の適切な処遇方法を開発し、心身の機能を回復し社会生活を営み得るようにす
る必要があったこと

から、どのように対策を立てていくかが課題であった。

国民皆保険の実現

・1922(大正11)年に制定された健康保険法は他の先進諸国と同様に、まず労働者(被用者)を対象として発足
・労働者以外の者にも医療保険の適用範囲を拡大するため、1938(昭和13)年に旧国民健康保険法が制定
医療保険制度の未適用者が、約2,871万人(総人口の約32%)存在し、大企業労働者と国保運営元市町村とそれ以外の市町村住民間の「二重構造」が問題視
・1958年3月に「新国民健康保険法」案を提出し、1958年12月に国会を通過
・翌1959年1月から施行され、当初の予定どおり、1961年4月に国民皆保険の体制が実現




通して参考
https://www.mhlw.go.jp/wp/hakusyo/kousei/14/dl/1-01.pdf

医薬品マスターをYAMLファイル化するRubyスクリプト

こんにちは!kossyです!




さて、今回は
診療報酬情報提供サービス
で提供されている医薬品マスターCSVYAMLファイル化するRubyスクリプトを書いてみたので、
ブログに残してみたいと思います。



環境
Ruby 2.6.3



コード全晒し

通常YAMLファイルを書き出す場合、YAML.dumpメソッドを用いるのですが、

iy_masters:
  - ["0", "0", "1234567", ...]
  - ["0", "0", "1234568", ...]


上記のように配列で1行ずつ定義することがどうしてもできず、
File.openで強引にやりたかったことを実現しています。

File.open('./tmp/iy_masters.yml', 'w') do |file|
  file.write 'iy_masters:' + "\n"
  CSV.read('./y.csv', encoding: 'Shift_JIS:UTF-8').each do |row| # マスターCSVがcurrentディレクトリにあることを想定
    file.write '  - '
    file.write row
    file.write "\n"
  end
end

このスクリプトを使えば他のマスターファイルにも応用できるかと思います。

出来上がったYAMLファイルはこちら
https://drive.google.com/file/d/1ITPOWA43kBepbIv0bV8WJQ6cVXfj1c2A/view