NotionRubyMapping の 2025-09-03対応(4) : hkob の雑記録 (250)

はじめに

hkob の雑記録の第248回目は、Notion API の Create a database の payload の変更対応について解説します。

Create a database

昨日依頼して修正してもらった Create a database のリファレンスページはこちらになります。

developers.notion.com

データベース自体は単なるコンテナになってしまったのでプロパティを持ちません。ただ、データソースは必ず一つは存在する必要があるので、最初のデータソースのプロパティだけは initial_data_source の下にこれまでの properties を設定できるようになっています。このため、PropertyCache の base_type に data_source も設定できるようにしました。この base_type の判定のために、以下の判定メソッドを用意しました。

    # @return [TrueClass, FalseClass] true if database type
    def database?
      @base_type == "database"
    end

    # @return [TrueClass, FalseClass] true if data_source type
    def data_source?
      @base_type == "data_source"
    end

    # @return [TrueClass, FalseClass] true if database or data_source type
    def database_or_data_source?
      %w[database data_source].include? @base_type
    end
    
    # @return [TrueClass, FalseClass] true if page type
    def page?
      @base_type == "page"
    end

これまで Create a database では property_schema を JSON の properties キーの下に設定して API を呼び出ししていました。この仕様は Create a data source では同じ設定となっています。一方で、上のリファレンスに書かれているように、Create a database ではこの property_schema を initial_data_source キーの下の properties に入れなくてはなりません。そこで、これまでの properties ハッシュを schema として一時保存し、database? の時だけ initial_data_source の下に記載するようにしました。

# @return [Hash] created property schema json
def property_schema_json
  schema = @properties.each_with_object({}) do |(_, property), ans|
    if property.will_update
      ans["properties"] ||= {}
      ans["properties"].merge! property.property_schema_json
    end
  end
  database? ? {"initial_data_source" => schema} : schema
end

# @return [Hash] created update property schema json
def update_property_schema_json
  schema = @properties.each_with_object({}) do |(_, property), ans|
    if property.will_update
      ans["properties"] ||= {}
      ans["properties"].merge! property.update_property_schema_json
    end
  end
  database? ? {"initial_data_source" => schema} : schema
end

これに合わせて、それぞれの property のクラスにも database? と data_source? を用意しました。また、それぞれで対応する機能が異なるので動作テストをしています。また、実装側でも異なる型のメソッドが呼ばれた時に例外が発生するように assert が用意されていましたが、ここも data_source? の判定を追加しています。

    # @param [Symbol, nil] method
    def assert_database_property(method)
      raise StandardError, "#{method} can execute only Database property." unless database?
    end

    # @param [Symbol, nil] method
    def assert_database_or_data_source_property(method)
      raise StandardError, "#{method} can execute only Database property." if page?
    end
    
    ## DataSource property only methods
    def assert_data_source_property(method)
      raise StandardError, "#{method} can execute only DataSource property." unless data_source?
    end

生成された databases の dry_run 結果はこのような感じになります。

curl -X POST 'https://api.notion.com/v1/databases/' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H 'Content-Type: application/json' \
  -H 'Notion-Version: 2025-09-03' \
  --data '{
    "parent": {
        "type": "page_id",
        "page_id": "c01166c613ae45cbb96818b4ef2f5a77"
    },
    "icon": {
        "type": "emoji",
        "emoji": "🎉"
    },
    "title":[{"type":"text","text":{"content":"New database title","link":null},"plain_text":"New database title","href":null}],
    "initial_data_source":{"properties":{"Checkbox":{"checkbox":{}},"CreatedBy":{"created_by":{}},"CreatedTime":{"created_time":{}},"Date":{"date":{}},"Email":{"email":{}},"Files":{"files":{}},"Formula":{"formula":{"expression":"now()"}},"LastEditedBy":{"last_edited_by":{}},"LastEditedTime":{"last_edited_time":{}},"MultiSelect":{"multi_select":{"options":[{"name":"MS1","color":"orange"},{"name":"MS2","color":"green"}]}},"Number":{"number":{"format":"yen"}},"People":{"people":{}},"PhoneNumber":{"phone_number":{}},"Relation":{"relation":{"data_source_id":"4f93db514e1d4015b07f876e34c3b0b1","type":"single_property","single_property":{}}},"Rollup":{"rollup":{"function":"sum","relation_property_name":"Relation","rollup_property_name":"NumberTitle"}},"RichText":{"rich_text":{}},"Select":{"select":{"options":[{"name":"S1","color":"yellow"},{"name":"S2","color":"default"}]}},"Title":{"title":{}},"Url":{"url":{}}}}}'

生成されたページは以下のようになりました。データベースにアイコンをつけても、データソースにはそれが影響しないようで、データソースのアイコンは空のままでした。これは最初のデータソースに付けて欲しいなと思います。

作成されたデータベース

参考までに Create a data source の dry_run はこのような形になり、properties が直下に入っています。

curl -X POST 'https://api.notion.com/v1/data_sources/' \\
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \\
  -H 'Content-Type: application/json' \\
  -H 'accept: application/json' \\
  -H 'Notion-Version: 2025-09-03' \\
  --data '{
    "parent": {
        "type": "database_id",
        "database_id": "2650ce2a6520808fbea9f247043f7f37"
    },
    "icon": {
        "type": "emoji",
        "emoji": "🎉"
    },
    "title":[{"type":"text","text":{"content":"New data source title","link":null},"plain_text":"New data source title","href":null}],
    "properties":{"Checkbox":{"checkbox":{}},"CreatedBy":{"created_by":{}},"CreatedTime":{"created_time":{}},"Date":{"date":{}},"Email":{"email":{}},"Files":{"files":{}},"Formula":{"formula":{"expression":"now()"}},"LastEditedBy":{"last_edited_by":{}},"LastEditedTime":{"last_edited_time":{}},"MultiSelect":{"multi_select":{"options":[{"name":"MS1","color":"orange"},{"name":"MS2","color":"green"}]}},"Number":{"number":{"format":"yen"}},"People":{"people":{}},"PhoneNumber":{"phone_number":{}},"Relation":{"relation":{"data_source_id":"2650ce2a6520809d991c000bf9cc5f17","type":"single_property","single_property":{}}},"Rollup":{"rollup":{"function":"sum","relation_property_name":"Relation","rollup_property_name":"NumberTitle"}},"RichText":{"rich_text":{}},"Select":{"select":{"options":[{"name":"S1","color":"yellow"},{"name":"S2","color":"default"}]}},"Title":{"title":{}},"Url":{"url":{}}}}'

おわりに

Create まで完了しました。もう少しで完了しそうです。

hkob.notion.site