はじめに
hkob の雑記録の第378回目(通算775日目)は、NotionRubyMapping に List data source templates を実装してみます。昨日はテストまで執筆したので、今日は Template object からテスト・実装していきます。
Template object のテストと実装
まず、テンプレートオブジェクトのテストを記載するために、template_object.json ファイルを作成しておきます。
{ "id": "88f4a106-b84b-4d35-9c2d-256bcd55901f", "name": "template", "is_default": true }
これを使ったテストを作成します。基本的に create_from_json だけ動作すればいいと思います。
# frozen_string_literal: true module NotionRubyMapping RSpec.describe TemplateObject do tc = TestConnection.instance template_json = tc.read_json "template_object" describe "create from json" do let(:target) { TemplateObject.new json: template_json } it_behaves_like "property values json", { "id" => "88f4a106-b84b-4d35-9c2d-256bcd55901f", "name" => "template", "is_default" => true, } it { expect(target.id).to eq "88f4a106-b84b-4d35-9c2d-256bcd55901f" } it { expect(target.name).to eq "template" } it { expect(target.is_default).to eq true } end end end
これが通過するように TemplateObject を実装します。
module NotionRubyMapping class TemplateObject def initialize(json: json) @id = json["id"] @name = json["name"] @is_default = json["is_default"] end attr_reader :id, :name, :is_default def property_values_json { "id" => @id, "name" => @name, "is_default" => @is_default } end end end
DataSource#templates の実装
昨日、DataSource#templates のテストを記述しました。こちらは API 呼び出しをして、返却された JSON から List object を作成すればいいので以下のようになります。
# @param [Integer] page_size # @return [NotionRubyMapping::List] List of Template object def templates(page_size: nil) json = @nc.list_data_source_templates_request(id, page_size: page_size) List.new type: "template", value: id, json: json, query: Query.new end
list_data_source_templates_request は API 呼び出しをするだけです。query_data_source などと異なり、この API は GET なので、payload で指定することができないためパスに含める必要があります。
# @param [String] data_source_id # @param [Integer] page_size # @param [String] start_cursor # @return [Hash] response hash def list_data_source_templates_request(data_source_id, page_size: nil, start_cursor: nil) options = [] options << "page_size=#{page_size}" if page_size options << "start_cursor=#{start_cursor}" if start_cursor option_str = options.empty? ? "" : "?" + options.join("&") request :get, list_data_source_templates_path(data_source_id, option_str) end
昨日、list_data_source_templates_path を作成してしまいましたが、引数が増えたので、テストを追加します。
describe "list_data_source_templates_path" do it { expect(nc.list_data_source_templates_path("ABC")).to eq "v1/data_sources/ABC/templates" } it { expect(nc.list_data_source_templates_path("DEF", "?page_size=1")).to eq "v1/data_sources/DEF/templates?page_size=1" } end
実装も修正します。
# @param [String] data_source_id # @param [String] options # @return [String] path def list_data_source_templates_path(data_source_id, options = "") "v1/data_sources/#{data_source_id}/templates#{options}" end
WebMock の stub も変更になるので修正します。
def list_data_source_templates generate_stubs_sub :get, __method__, :list_data_source_templates_path, { no_limit: [DATA_SOURCE_ID, 200], limit_1: [[DATA_SOURCE_ID, "?page_size=1"], 200], next_1: [[DATA_SOURCE_ID, "?start_cursor=2e5d8e4e-98ab-808f-8c3a-f0819e3b3567"], 200], } end
ここまでで、無事に API 呼び出しは実行でき、response までは取得できました。あとは、response から List object が生成する部分を実装すればよいことになります。
1) NotionRubyMapping::DataSource templates when no limit is expected to eq 2 Failure/Error: it { expect(templates.count).to eq 2 } expected: 2 got: 0 (compared using ==) # ./spec/notion_ruby_mapping/blocks/data_source_spec.rb:59:in 'block (4 levels) in <module:NotionRubyMapping>'
response から List object を生成
まず、List の initialize で template type に対応するようにします。@template の中には Data source の id が保持されます。
def initialize(json: nil, id: nil, type: nil, value: nil, query: nil) super(json: json, id: id) @has_more = @json["has_more"] @load_all_contents = !@has_more case type when "comment_parent" @comment_parent = value when "data_source" @data_source = value when "parent" @parent = value when "property" @property = value when "user_object" @user_object = value when "search" @search = value when "template" @template = value end @query = query @index = 0 @has_content = true end
通常の List object では results キーに情報が入っていますが、template の場合は templates キーに含まれています。このため、results メソッドで場合分けをすればよさそうです。
# @return [Hash] def results @json[@template ? "templates" : "results"] end
あとは、each で TemplateObject を作成する部分だけです。each_sub の部分で Pagination の部分は汎化しておいたので、次の query 呼び出しと一つ一つのオブジェクト生成のブロック呼び出しだけ指定するだけで済みました。
# @return [NotionRubyMapping::List, Enumerator] # @see <https://www.notion.so/hkob/List-9a0b32335e0d48849a785ce5e162c760#12e1c261a0944a4095776b7515bef4a1> def each(&block) return enum_for(:each) if block.nil? if @parent (中略) elsif @template each_sub base: @template, query: -> { @nc.list_data_source_templates_request @template, start_cursor: @query.start_cursor }, create_object: ->(json) { TemplateObject.new json: json }, &block end self end
これでテストは無事に全て通過しました。全て読めた場合も、Pagination した場合も全てのテンプレートが無事に取得できていることがわかります。
templates
when no limit
is expected to eq 2
is expected to eq ["template", "another template"]
is expected to eq ["88f4a106-b84b-4d35-9c2d-256bcd55901f", "2e5d8e4e-98ab-808f-8c3a-f0819e3b3567"]
when limit 1
is expected to eq 2
is expected to eq ["template", "another template"]
is expected to eq ["88f4a106-b84b-4d35-9c2d-256bcd55901f", "2e5d8e4e-98ab-808f-8c3a-f0819e3b3567"]
おわりに
List data source templates API は List object を返却しませんが、内容的には List object と同様の Pagination をするので、NotionRubyMapping では List object に集約してしまいました。そのおかげで実装はほとんど修正の必要がなく、記述することができました。