はじめに
hkob の雑記録の第390回目(通算786日目)は、NotionRubyMapping に position object を追加します。前回作成したテストをもとに実装を作成します。
create_child_page を実装
今、data_source.rb には create_child_page が以下のように実装されています。
# @param [Array<Property, Class, String>] assign # @return [NotionRubyMapping::Base] # @see https://www.notion.so/hkob/DataSource-1462b24502424539a4231bedc07dc2f5#c217ce78020a4de79b720790fce3092d def build_child_page(*assign, template_page: nil) assign = properties.map { |p| [p.class, p.name] }.flatten if assign.empty? page = Page.new assign: assign, parent: {"data_source_id" => @id}, template_page: template_page pp = page.properties pp.clear_will_update yield page, pp if block_given? page end # @param [Array<Property, Class, String>] assign # @param [Boolean] dry_run true if dry_run # @return [NotionRubyMapping::Base] # @see https://www.notion.so/hkob/DataSource-1462b24502424539a4231bedc07dc2f5#c217ce78020a4de79b720790fce3092d def create_child_page(*assign, template_page: nil, dry_run: false) assign = properties.map { |p| [p.class, p.name] }.flatten if assign.empty? page = Page.new assign: assign, parent: {"data_source_id" => @id}, template_page: template_page pp = page.properties pp.clear_will_update yield page, pp if block_given? page.save dry_run: dry_run end
これをもとに Page#create_child_page を作成します。一昨日のテストの際に記述したように、Page 内に Page を作る時には Title property しか持たないので、引数を受け付けずに TitleProperty を自動的に作成します。また、position を引数で受けるようにしています。
# @return [NotionRubyMapping::Base] def build_child_page(template_page: nil, position: nil) page = Page.new assign: [TitleProperty, "title"], parent: {"type" => "page_id", "page_id" => @id}, template_page: template_page, position: position pp = page.properties pp.clear_will_update yield page, pp if block_given? page end # @param [Boolean] dry_run true if dry_run # @return [NotionRubyMapping::Base] def create_child_page(template_page: nil, position: nil, dry_run: false) page = Page.new assign: [TitleProperty, "title"], parent: {"type" => "page_id", "page_id" => @id}, template_page: template_page, position: position pp = page.properties pp.clear_will_update yield page, pp if block_given? page.save dry_run: dry_run end
Page に position の引数を設定する必要があります。これは Page の親クラスである Base に設定します。先日追加した template_page の後ろに position の設定を追加しました。
class Base # @param [Hash, nil] json # @param [String, nil] id # @param [Array<Property, Class, String>] assign def initialize(json: nil, id: nil, assign: [], parent: nil, template_page: nil, position: nil) @nc = NotionCache.instance @json = json @id = @nc.hex_id(id || @json && @json["id"]) @archived = @json && @json["archived"] @has_children = @json && @json["has_children"] @new_record = true unless parent.nil? raise StandardError, "Unknown id" if !is_a?(List) && !is_a?(Block) && @id.nil? && parent.nil? payload_json = {} payload_json["parent"] = parent if !is_a?(Block) && parent if template_page == "default" payload_json["template"] = {"type" => "default"} elsif template_page payload_json["template"] = {"type" => "template_id", "template_id" => template_page.id} end if %w[page_start page_end].include? position payload_json["position"] = {"type" => position} elsif position payload_json["position"] = {"type" => "after_block", "after_block" => {"id" => position}} end @payload = Payload.new(payload_json) (後略)
これで dry_run のスクリプト作成まではテストが通りました。あとは WebMock の設定をすれば、実際のアクセステストでもテストが通過するはずです。WebMock の関数に以下の設定を追加しました。
def create_page generate_stubs_sub :post, __method__, :pages_path, { (中略) page_start: [nil, 200, { "properties" => { "title" => { "type" => "title", "title" => [ { "type" => "text", "text" => { "content" => "New Page at page_start", "link" => nil, }, "plain_text" => "New Page at page_start", "href" => nil, }, ], }, }, "parent" => { "type" => "page_id", "page_id" => TestConnection::POSITION_TEST_PARENT_PAGE_ID, }, "position" => { "type" => "page_start", }, }], page_end: [nil, 200, { "properties" => { "title" => { "type" => "title", "title" => [ { "type" => "text", "text" => { "content" => "New Page at page_end", "link" => nil, }, "plain_text" => "New Page at page_end", "href" => nil, }, ], }, }, "parent" => { "type" => "page_id", "page_id" => TestConnection::POSITION_TEST_PARENT_PAGE_ID, }, "position" => { "type" => "page_end", }, }], after_block: [nil, 200, { "properties" => { "title" => { "type" => "title", "title" => [ { "type" => "text", "text" => { "content" => "New Page at after_block", "link" => nil, }, "plain_text" => "New Page at after_block", "href" => nil, }, ], }, }, "parent" => { "type" => "page_id", "page_id" => TestConnection::POSITION_TEST_PARENT_PAGE_ID, }, "position" => { "type" => "after_block", "after_block" => { "id" => "2f0d8e4e98ab812ca8f5cce62b2d3f6e", }, }, }], } end
最終的にテストは全て通過しました。
position object for create a page when it creates at page_end when not dry_run is expected to eq "2f0d8e4e98ab818d8366c12b276c6a7c" is expected to eq "2f0d8e4e98ab8065b3a2ec9fd4b3e57a" when dry_run behaves like dry run is expected to eq "#!/bin/sh\ncurl -X POST 'https://api.notion.com/v1/pages' \\\n -H 'Notion-Version: 2025-09-03' \\\n..."page_id\",\"page_id\":\"2f0d8e4e98ab8065b3a2ec9fd4b3e57a\"},\"position\":{\"type\":\"page_end\"}}'" when it creates at page_start when not dry_run is expected to eq "2f0d8e4e98ab812ca8f5cce62b2d3f6e" is expected to eq "2f0d8e4e98ab8065b3a2ec9fd4b3e57a" when dry_run behaves like dry run is expected to eq "#!/bin/sh\ncurl -X POST 'https://api.notion.com/v1/pages' \\\n -H 'Notion-Version: 2025-09-03' \\\n...age_id\",\"page_id\":\"2f0d8e4e98ab8065b3a2ec9fd4b3e57a\"},\"position\":{\"type\":\"page_start\"}}'" when it creates at after_block when not dry_run is expected to eq "2f0d8e4e98ab818b9968fc9ec363ed6b" is expected to eq "2f0d8e4e98ab8065b3a2ec9fd4b3e57a" when dry_run behaves like dry run is expected to eq "#!/bin/sh\ncurl -X POST 'https://api.notion.com/v1/pages' \\\n -H 'Notion-Version: 2025-09-03' \\\n...sition\":{\"type\":\"after_block\",\"after_block\":{\"id\":\"2f0d8e4e98ab812ca8f5cce62b2d3f6e\"}}}'" Finished in 0.11899 seconds (files took 0.46668 seconds to load) 129 examples, 0 failures
おわりに
これで Page#create_child_page の実装も追加されました。ここまでをまとめて新しいバージョンのリリースをしてしまおうと思います。