はじめに
hkob の雑記録の第425回目(通算19日目)も、NotionRubyMapping を makedown に対応させます。今日は、マークダウンを特定の場所に追加する Page#insert_markdown メソッドを作成します。
テストデータの作成
最初、markdown の GET を実装しようとしたのですが、 "message": "Only public integrations can access this API.", というエラーが出てしまいました。こちらのページに記載がありました。
public integrations にしか対応していないようですね。
This endpoint is restricted to public integrations only. Internal integrations (workspace-level bots) will receive a restricted_resource error. Use the block-based API instead for internal integrations.
まずはいつものようにスクリプト作成です。最初は after を指示せず、ページの末端に追加します。
curl 'https://api.notion.com/v1/pages/315d8e4e98ab8108901dcfa2d3993f6e/markdown' \ -H 'Notion-Version: 2025-09-03' \ -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \ -H "Content-Type: application/json" \ -X PATCH \ --data '{ "type": "insert_content", "insert_content": { "content": "- Added new item in page bottom\n" } }'
make するとページの一番下に箇条書きが追加されました。

markdown の GET はできませんが、insert の返り値としては markdown が返却されるのですね。
{ "object": "page_markdown", "id": "315d8e4e-98ab-8108-901d-cfa2d3993f6e", "markdown": "## Paragraph 2\n- [ ] To Do\n- [x] Checked To Do\n- Added new item in page bottom", "truncated": false, "unknown_block_ids": [], "request_id": "d19f3038-b10d-4c11-8422-7d6726d47130" }
もう一つ after を指定した場合も追加してみます。
curl 'https://api.notion.com/v1/pages/315d8e4e98ab8108901dcfa2d3993f6e/markdown' \ -H 'Notion-Version: 2025-09-03' \ -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \ -H "Content-Type: application/json" \ -X PATCH \ --data '{ "type": "insert_content", "insert_content": { "content": "1. Added numbered item after To Do item\n", "after": "- [ ] To Do\n" } }'
正しく、To Do の後ろに追加されました。

テストの記述
まずは page bottom への挿入だけテストしてみます。今回、返却されるのは page_markdown ですが、Page object に markdown だけ登録する形にしてみようと思います。
describe "insert markdown" do let(:pid) { TestConnection::NEW_PAGE_WITH_MARKDOWN_PAGE_ID } let(:page) { Page.new id: pid } context "when insert bottom" do markdown = "- Added new item in page bottom\n" let(:target) { page.insert_markdown markdown } context "when not dry_run" do it { expect(target.id).to eq pid } it { expect(target.markdown).to eq "## Paragraph 2\n- [ ] To Do\n- [x] Checked To Do\n- Added new item in page bottom" } end context "when dry_run" do it_behaves_like "dry run", :patch, :markdown_page_path, use_id: true, json: { "markdown" => markdown, } end end end
当然 undefined method になります。
NoMethodError: undefined method 'insert_markdown' for an instance of NotionRubyMapping::Page
実装の作成
json を作成して markdown_page_path に関するメソッドなどを呼べばいいはずです。
# @param [String] markdown # @param [Boolean] dry_run # @return [String, NotionRubyMapping::Base] def insert_markdown(markdown, dry_run: false) json = {"type" => "insert_content", "insert_content" => {"content" => markdown}} if dry_run self.class.dry_run_script :patch, @nc.markdown_page_path(@id), json else update_json @nc.markdown_page_request(@id, json) end end
markdown_page_path はないのでテストを書きます。
describe "markdown_page_path" do it { expect(nc.markdown_page_path("ABC")).to eq "v1/pages/ABC/markdown" } end
markdown_page_path と markdown_page_request を追加してみます。
# @param [String] page_id # @return [String] path def markdown_page_path(page_id) "v1/pages/#{page_id}/markdown" end # @param [String] page_id # @param [Hash] payload # @return [Hash] response hash def markdown_page_request(page_id, payload) request :patch, markdown_page_path(page_id), payload end
WebMock の追加
markdown_page に関する WebMock を追加します。
def markdown_page generate_stubs_sub :patch, __method__, :markdown_page_path, { by_insert_bottom: [ NEW_PAGE_WITH_MARKDOWN_PAGE_ID, 200, { "type" => "insert_content", "insert_content" => { "content" => "- Added new item in page bottom\n", }, } ], } end
Base の修正
上にも書いたように page_markdown が返却されても Page object を生成して欲しいです。object が page_markdown の場合にも Page.new を実行します。
# @param [Hash, Notion::Messages] json # @return [NotionRubyMapping::Base] def self.create_from_json(json) case json["object"] when "page", "page_markdown" Page.new json: json when "data_source" DataSource.new json: json when "database" Database.new json: json when "list" List.new json: json when "block" Block.decode_block json else raise StandardError, json.inspect end end
あとは markdown だけ取得したいです。@json に入っているので、その markdown キーを返すようにしましょう。
# @return [String] def markdown @json && @json["markdown"] end
無事にテストが通過しました。
insert markdown
when insert bottom
when not dry_run
is expected to eq "315d8e4e98ab8108901dcfa2d3993f6e"
is expected to eq "## Paragraph 2\n- [ ] To Do\n- [x] Checked To Do\n- Added new item in page bottom"
when dry_run
behaves like dry run
is expected to eq "#!/bin/sh\ncurl -X PATCH 'https://api.notion.com/v1/pages/315d8e4e98ab8108901dcfa2d3993f6e/markdown'...type\":\"insert_content\",\"insert_content\":{\"content\":\"- Added new item in page bottom\\n\"}}'"
Finished in 0.148 seconds (files took 0.36512 seconds to load)
145 examples, 0 failures
after のテストを追加
追加したテストはこちらです。
context "when insert after to do" do markdown = "1. Added numbered item after To Do item\n" after = "- [ ] To Do\n" let(:target) { page.insert_markdown markdown, after: after } context "when not dry_run" do it { expect(target.id).to eq pid } it { expect(target.markdown).to eq "## Paragraph 2\n- [ ] To Do\n1. Added numbered item after To Do item\n- [x] Checked To Do\n- Added new item in page bottom\n<empty-block/>" } end context "when dry_run" do let(:dry_run) { page.insert_markdown markdown, after: after, dry_run: true } it_behaves_like "dry run", :patch, :markdown_page_path, use_id: true, json: { "type" => "insert_content", "insert_content" => { "content" => markdown, "after" => after, }, } end end
insert_markdown に after キーワード引数を追加します。
# @param [String] markdown # @param [String, NilClass] after # @param [Boolean] dry_run # @return [String, NotionRubyMapping::Base] def insert_markdown(markdown, after: nil, dry_run: false) json = {"type" => "insert_content", "insert_content" => {"content" => markdown}} json["insert_content"]["after"] = after if after if dry_run self.class.dry_run_script :patch, @nc.markdown_page_path(@id), json else update_json @nc.markdown_page_request(@id, json) end end
あとは WebMock を更新するだけです。
def markdown_page generate_stubs_sub :patch, __method__, :markdown_page_path, { by_insert_bottom: [ NEW_PAGE_WITH_MARKDOWN_PAGE_ID, 200, { "type" => "insert_content", "insert_content" => { "content" => "- Added new item in page bottom\n", }, } ], by_insert_after_todo: [ NEW_PAGE_WITH_MARKDOWN_PAGE_ID, 200, { "type" => "insert_content", "insert_content" => { "content" => "1. Added numbered item after To Do item\n", "after" => "- [ ] To Do\n", }, } ], } end
これで無事に全てのテストが通過しました。
insert markdown
when insert bottom
when not dry_run
is expected to eq "315d8e4e98ab8108901dcfa2d3993f6e"
is expected to eq "## Paragraph 2\n- [ ] To Do\n- [x] Checked To Do\n- Added new item in page bottom"
when dry_run
behaves like dry run
is expected to eq "#!/bin/sh\ncurl -X PATCH 'https://api.notion.com/v1/pages/315d8e4e98ab8108901dcfa2d3993f6e/markdown'...type\":\"insert_content\",\"insert_content\":{\"content\":\"- Added new item in page bottom\\n\"}}'"
when insert after to do
when not dry_run
is expected to eq "315d8e4e98ab8108901dcfa2d3993f6e"
is expected to eq "## Paragraph 2\n- [ ] To Do\n1. Added numbered item after To Do item\n- [x] Checked To Do\n- Added new item in page bottom\n<empty-block/>"
when dry_run
behaves like dry run
is expected to eq "#!/bin/sh\ncurl -X PATCH 'https://api.notion.com/v1/pages/315d8e4e98ab8108901dcfa2d3993f6e/markdown'...ntent\":{\"content\":\"1. Added numbered item after To Do item\\n\",\"after\":\"- [ ] To Do\\n\"}}'"
Finished in 0.22883 seconds (files took 0.56389 seconds to load)
148 examples, 0 failures
おわりに
markdown の GET が使えなかったので、insert_markdown を実装しました。明日は replace_markdown を実装します。