notion_ruby_mapping 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Guardfile +1 -1
  3. data/README.md +494 -268
  4. data/env.yml.sample +7 -0
  5. data/lib/notion_ruby_mapping/base.rb +37 -30
  6. data/lib/notion_ruby_mapping/checkbox_property.rb +26 -0
  7. data/lib/notion_ruby_mapping/created_by_property.rb +21 -0
  8. data/lib/notion_ruby_mapping/created_time_property.rb +20 -0
  9. data/lib/notion_ruby_mapping/database.rb +8 -8
  10. data/lib/notion_ruby_mapping/date_base_property.rb +40 -38
  11. data/lib/notion_ruby_mapping/date_property.rb +42 -18
  12. data/lib/notion_ruby_mapping/email_property.rb +30 -1
  13. data/lib/notion_ruby_mapping/files_property.rb +40 -0
  14. data/lib/notion_ruby_mapping/formula_property.rb +18 -0
  15. data/lib/notion_ruby_mapping/last_edited_by_property.rb +21 -0
  16. data/lib/notion_ruby_mapping/last_edited_time_property.rb +20 -0
  17. data/lib/notion_ruby_mapping/list.rb +33 -2
  18. data/lib/notion_ruby_mapping/mention_object.rb +49 -0
  19. data/lib/notion_ruby_mapping/multi_select_property.rb +25 -6
  20. data/lib/notion_ruby_mapping/notion_cache.rb +126 -53
  21. data/lib/notion_ruby_mapping/number_property.rb +13 -8
  22. data/lib/notion_ruby_mapping/page.rb +5 -2
  23. data/lib/notion_ruby_mapping/payload.rb +10 -2
  24. data/lib/notion_ruby_mapping/people_property.rb +38 -0
  25. data/lib/notion_ruby_mapping/phone_number_property.rb +30 -1
  26. data/lib/notion_ruby_mapping/property.rb +79 -43
  27. data/lib/notion_ruby_mapping/property_cache.rb +31 -12
  28. data/lib/notion_ruby_mapping/query.rb +5 -2
  29. data/lib/notion_ruby_mapping/relation_property.rb +37 -0
  30. data/lib/notion_ruby_mapping/rich_text_object.rb +74 -0
  31. data/lib/notion_ruby_mapping/rich_text_property.rb +18 -0
  32. data/lib/notion_ruby_mapping/rollup_property.rb +29 -0
  33. data/lib/notion_ruby_mapping/select_property.rb +12 -6
  34. data/lib/notion_ruby_mapping/text_object.rb +89 -0
  35. data/lib/notion_ruby_mapping/text_property.rb +61 -0
  36. data/lib/notion_ruby_mapping/title_property.rb +18 -0
  37. data/lib/notion_ruby_mapping/url_property.rb +30 -1
  38. data/lib/notion_ruby_mapping/user_object.rb +38 -0
  39. data/lib/notion_ruby_mapping/version.rb +2 -1
  40. data/lib/notion_ruby_mapping.rb +3 -3
  41. data/notion_ruby_mapping.gemspec +3 -1
  42. metadata +40 -7
@@ -5,12 +5,43 @@ module NotionRubyMapping
5
5
  class List < Base
6
6
  include Enumerable
7
7
 
8
+ def initialize(json: nil, id: nil, database: nil, query: nil)
9
+ super(json: json, id: id)
10
+ @has_more = @json["has_more"]
11
+ @database = database
12
+ @query = query
13
+ @index = 0
14
+ @has_content = true
15
+ end
16
+ attr_reader :has_more
17
+
8
18
  def each
9
19
  return enum_for(:each) unless block_given?
10
20
 
11
- json["results"].each do |block_json|
12
- yield Base.create_from_json(block_json)
21
+ while @has_content
22
+ if @index < results.length
23
+ object = Base.create_from_json(results[@index])
24
+ @index += 1
25
+ yield object
26
+ elsif @has_more
27
+ if @database
28
+ @query.start_cursor = @json["next_cursor"]
29
+ @json = @database.query_database @query
30
+ @index = 0
31
+ @has_more = @json["has_more"]
32
+ else
33
+ @has_content = false
34
+ end
35
+ else
36
+ @has_content = false
37
+ end
13
38
  end
14
39
  end
40
+
41
+ private
42
+
43
+ def results
44
+ @json["results"]
45
+ end
15
46
  end
16
47
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # TextObject
5
+ class MentionObject < RichTextObject
6
+ # @return [MentionObject]
7
+ def initialize(options = {})
8
+ super "mention", options
9
+ end
10
+
11
+ # @return [String (frozen)]
12
+ def text
13
+ ""
14
+ end
15
+
16
+ def partial_property_values_json
17
+ if @options.key? "user_id"
18
+ {
19
+ "type" => "user",
20
+ "user" => {
21
+ "object" => "user",
22
+ "id" => @options["user_id"],
23
+ },
24
+ }
25
+ elsif @options.key? "page_id"
26
+ {
27
+ "type" => "page",
28
+ "page" => {
29
+ "id" => @options["page_id"],
30
+ },
31
+ }
32
+ elsif @options.key? "database_id"
33
+ {
34
+ "type" => "database",
35
+ "database" => {
36
+ "id" => @options["database_id"],
37
+ },
38
+ }
39
+ elsif @options.key? "start"
40
+ {
41
+ "type" => "date",
42
+ "date" => @options.slice("start", "end", "time_zone"),
43
+ }
44
+ else
45
+ raise StandardError, "Irregular mention type"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -3,26 +3,45 @@
3
3
  module NotionRubyMapping
4
4
  # MultiSelect property
5
5
  class MultiSelectProperty < MultiProperty
6
+ include ContainsDoesNotContain
7
+ include IsEmptyIsNotEmpty
6
8
  TYPE = "multi_select"
7
9
 
8
10
  # @param [String] name
9
11
  # @param [Hash] json
10
12
  # @param [Array] multi_select
11
- def initialize(name, json: nil, multi_select: nil)
12
- super(name, json: json)
13
- @multi_select = multi_select ? Array(multi_select) : nil
13
+ def initialize(name, will_update: false, json: nil, multi_select: nil)
14
+ super name, will_update: will_update
15
+ @multi_select = if multi_select
16
+ Array(multi_select)
17
+ elsif json.is_a? Array
18
+ json.map { |ms| ms["name"] }
19
+ else
20
+ []
21
+ end
14
22
  end
15
23
 
16
24
  # @return [Hash] created json
17
- def create_json
18
- {"multi_select" => @multi_select ? (@multi_select.map { |v| {"name" => v} }) : @json} || {}
25
+ def property_values_json
26
+ {
27
+ @name => {
28
+ "type" => "multi_select",
29
+ "multi_select" => @multi_select.map { |v| {"name" => v} },
30
+ },
31
+ }
19
32
  end
20
33
 
21
34
  # @param [Hash] multi_select
22
35
  # @return [Array, nil] settled array
23
36
  def multi_select=(multi_select)
24
37
  @will_update = true
25
- @multi_select = multi_select ? Array(multi_select) : nil
38
+ @multi_select = multi_select ? Array(multi_select) : []
39
+ end
40
+
41
+ # @param [Hash] json
42
+ def update_from_json(json)
43
+ @will_update = false
44
+ @multi_select = json["multi_select"].map { |ms| ms["name"] }
26
45
  end
27
46
  end
28
47
  end
@@ -1,28 +1,129 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "singleton"
4
- require "notion"
4
+ require "faraday"
5
+ require "faraday_middleware"
5
6
 
6
7
  module NotionRubyMapping
7
8
  # singleton class of caching Notion objects
8
9
  class NotionCache
9
10
  include Singleton
10
11
 
12
+ ### initialize
13
+
11
14
  def initialize
12
15
  @object_hash = {}
13
- @client = nil
16
+ @client = Faraday::Connection.new "https://api.notion.com" do |builder|
17
+ builder.use FaradayMiddleware::EncodeJson
18
+ builder.use FaradayMiddleware::ParseJson
19
+ builder.adapter Faraday.default_adapter
20
+ end
21
+ @notion_token = nil
14
22
  @wait = 0
23
+ @debug = false
15
24
  end
16
- attr_reader :object_hash, :client
25
+ attr_reader :object_hash
26
+ attr_writer :client # for test only
17
27
 
18
28
  # @param [String] notion_token
19
29
  # @return [NotionRubyMapping::NotionCache] self (NotionCache.instance)
20
- def create_client(notion_token, wait = 0.3333)
21
- @client ||= Notion::Client.new token: notion_token
30
+ def create_client(notion_token, wait: 0.3333, debug: false)
31
+ @notion_token = notion_token
22
32
  @wait = wait
33
+ @debug = debug
23
34
  self
24
35
  end
25
36
 
37
+ ### create path methods
38
+
39
+ # @param [String] page_id
40
+ # @return [String (frozen)] page_path
41
+ def page_path(page_id)
42
+ "v1/pages/#{page_id}"
43
+ end
44
+
45
+ # @param [String] database_id
46
+ # @return [String (frozen)] page_path
47
+ def database_path(database_id)
48
+ "v1/databases/#{database_id}"
49
+ end
50
+
51
+ # @param [String] block_id
52
+ # @return [String (frozen)] page_path
53
+ def block_path(block_id)
54
+ "v1/blocks/#{block_id}"
55
+ end
56
+
57
+ # @param [String] database_id
58
+ # @return [String (frozen)] page_path
59
+ def query_database_path(database_id)
60
+ "v1/databases/#{database_id}/query"
61
+ end
62
+
63
+ ### Notion API call
64
+
65
+ # @param [Symbol] method
66
+ # @param [String] path
67
+ # @param [Hash] options
68
+ # @return [Hash] response hash
69
+ def request(method, path, options = {})
70
+ raise "Please call `NotionCache.create_client' before using other methods" unless @notion_token
71
+
72
+ sleep @wait
73
+ response = @client.send(method) do |request|
74
+ request.headers["Authorization"] = "Bearer #{@notion_token}"
75
+ request.headers["Notion-Version"] = NotionRubyMapping::NOTION_VERSION
76
+ case method
77
+ when :get, :delete
78
+ request.url path, options
79
+ when :post, :put, :patch
80
+ request.headers["Content-Type"] = "application/json"
81
+ request.path = path
82
+ request.body = options.to_json unless options.empty?
83
+ else
84
+ raise StandardError, "Unknown method: #{method}"
85
+ end
86
+ request.options.merge!(options.delete(:request)) if options.key? :request
87
+ end
88
+ p response.body if @debug
89
+ response.body
90
+ end
91
+
92
+ # @param [String] page_id
93
+ # @return [Hash] response
94
+ def page_request(page_id)
95
+ request :get, page_path(page_id)
96
+ end
97
+
98
+ # @param [String] database_id
99
+ # @return [Hash] response
100
+ def database_request(database_id)
101
+ request :get, database_path(database_id)
102
+ end
103
+
104
+ def database_query_request(database_id, payload)
105
+ request :post, "v1/databases/#{database_id}/query", payload
106
+ end
107
+
108
+ # @param [String] block_id
109
+ # @return [Hash] response
110
+ def block_request(block_id)
111
+ request :get, block_path(block_id)
112
+ end
113
+
114
+ # @param [String] database_id
115
+ # @return [Hash] response
116
+ def update_database_request(database_id, payload)
117
+ request :patch, "v1/databases/#{database_id}", payload
118
+ end
119
+
120
+ # @param [String] page_id
121
+ # @param [Hash] payload
122
+ # @return [Hash] response
123
+ def update_page_request(page_id, payload)
124
+ request :patch, "v1/pages/#{page_id}", payload
125
+ end
126
+
26
127
  # @param [String] id id string with "-"
27
128
  # @return [String] id without "-"
28
129
  def hex_id(id)
@@ -30,59 +131,35 @@ module NotionRubyMapping
30
131
  end
31
132
 
32
133
  # @param [String] id id (with or without "-")
33
- # @return [NotionRubyMapping::Block, NotionRubyMapping::List, NotionRubyMapping::Database, NotionRubyMapping::Page, nil]
134
+ # @return [NotionRubyMapping::Base]
34
135
  def object_for_key(id)
35
136
  key = hex_id(id)
36
137
  return @object_hash[key] if @object_hash.key? key
37
138
 
38
- begin
39
- json = yield(@client)
40
- @object_hash[key] = Base.create_from_json json
41
- rescue StandardError
42
- nil
43
- end
44
- end
45
-
46
- # @param [String] id page_id (with or without "-")
47
- # @return [Hash] obtained json
48
- def page_json(id)
49
- sleep @wait
50
- @client.page page_id: id
139
+ json = yield(@client)
140
+ @object_hash[key] = Base.create_from_json json
51
141
  end
52
142
 
53
143
  # @param [String] id page_id (with or without "-")
54
- # @return [NotionRubyMapping::Page, nil] Page object or nil
144
+ # @return [NotionRubyMapping::Base] Page object or nil
55
145
  def page(id)
56
- object_for_key(id) { page_json id }
146
+ object_for_key(id) { page_request id }
57
147
  end
58
148
 
59
149
  # @param [String] id database_id (with or without "-")
60
- # @return [Hash] obtained json
61
- def database_json(id)
62
- sleep @wait
63
- @client.database database_id: id
64
- end
65
-
66
- # @param [String] id database_id (with or without "-")
67
- # @return [NotionRubyMapping::Database, nil] Database object or nil
150
+ # @return [NotionRubyMapping::Base] Database object or nil
68
151
  def database(id)
69
- object_for_key(id) { database_json id }
152
+ object_for_key(id) { database_request id }
70
153
  end
71
154
 
72
155
  # @param [String] id block_id (with or without "-")
73
- # @return [Hash] obtained json
74
- def block_json(id)
75
- sleep @wait
76
- @client.block block_id: id
77
- end
78
- # @param [String] id block_id (with or without "-")
79
- # @return [NotionRubyMapping::Block, nil] Block object or nil
156
+ # @return [NotionRubyMapping::Base] Block object or nil
80
157
  def block(id)
81
- object_for_key(id) { block_json id }
158
+ object_for_key(id) { block_request id }
82
159
  end
83
160
 
84
161
  # @param [String] id page_id / block_id (with or without "-")
85
- # @return [NotionRubyMapping::List] List object
162
+ # @return [NotionRubyMapping::Base] List object
86
163
  def block_children(id)
87
164
  array = []
88
165
  sleep @wait
@@ -94,24 +171,15 @@ module NotionRubyMapping
94
171
 
95
172
  # @param [String] id page_id / block_id (with or without "-")
96
173
  # @param [NotionRubyMapping::Query] query query object
97
- # @return [NotionRubyMapping::List] List object
174
+ # @return [NotionRubyMapping::Base] List object
98
175
  def database_query(id, query)
99
- array = []
100
- parameters = {database_id: id, sleep_interval: @wait, max_retries: 20}
176
+ parameters = {}
101
177
  parameters[:filter] = query.filter unless query.filter.empty?
102
178
  parameters[:sorts] = query.sort unless query.sort.empty?
179
+ parameters[:start_cursor] = query.start_cursor if query.start_cursor
180
+ parameters[:page_size] = query.page_size if query.page_size
103
181
 
104
- @client.database_query(parameters) do |page|
105
- array.concat page.results
106
- end
107
- Base.create_from_json({"object" => "list", "results" => array})
108
- end
109
-
110
- # @param [String] id page_id (with or without "-")
111
- # @param [Hash] payload
112
- def update_page(id, payload)
113
- sleep @wait
114
- @client.update_page payload.merge({page_id: id})
182
+ Base.create_from_json database_query_request(id, parameters)
115
183
  end
116
184
 
117
185
  # @param [String] id page_id (with or without "-")
@@ -120,5 +188,10 @@ module NotionRubyMapping
120
188
  sleep @wait
121
189
  @client.update_database payload.merge({database_id: id})
122
190
  end
191
+
192
+ # @return [Hash]
193
+ def clear_object_hash
194
+ @object_hash = {}
195
+ end
123
196
  end
124
197
  end
@@ -9,22 +9,27 @@ module NotionRubyMapping
9
9
  TYPE = "number"
10
10
 
11
11
  # @param [String] name Property name
12
- # @param [Hash] json
13
- # @param [Float] number Number value (optional)
14
- def initialize(name, json: nil, number: nil)
15
- super(name, json: json)
12
+ # @param [Float, Integer] number Number value (optional)
13
+ def initialize(name, will_update: false, number: nil)
14
+ super name, will_update: will_update
16
15
  @number = number
17
16
  end
18
17
  attr_reader :number
19
18
 
19
+ # @param [Hash] json
20
+ def update_from_json(json)
21
+ @will_update = false
22
+ @number = json["number"]
23
+ end
24
+
20
25
  # @return [Hash]
21
- def create_json
22
- {"number" => @number || @json}
26
+ def property_values_json
27
+ {@name => {"number" => @number, "type" => "number"}}
23
28
  end
24
29
 
25
- def number=(n)
30
+ def number=(num)
26
31
  @will_update = true
27
- @number = n
32
+ @number = num
28
33
  end
29
34
  end
30
35
  end
@@ -7,13 +7,16 @@ module NotionRubyMapping
7
7
  NotionCache.instance.page id
8
8
  end
9
9
 
10
+ # @return [NotionRubyMapping::Base]
10
11
  def update
11
- update_json @nc.update_page(@id, create_json)
12
+ update_json @nc.update_page_request(@id, property_values_json)
12
13
  end
13
14
 
15
+ protected
16
+
14
17
  # @return [Hash]
15
18
  def reload_json
16
- @nc.page_json @id
19
+ @nc.page_request @id
17
20
  end
18
21
  end
19
22
  end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NotionRubyMapping
4
+ # Payload class
2
5
  class Payload
3
6
  def initialize
4
7
  @json = {}
@@ -20,9 +23,14 @@ module NotionRubyMapping
20
23
  end
21
24
 
22
25
  # @return [Hash] created json
23
- # @param optional [Hash] optional_json
24
- def create_json(optional_json = nil)
26
+ # @param [Hash] optional_json
27
+ def property_values_json(optional_json = nil)
25
28
  @json.merge(optional_json || {})
26
29
  end
30
+
31
+ # @return [Hash] {}
32
+ def clear
33
+ @json = {}
34
+ end
27
35
  end
28
36
  end
@@ -1,7 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NotionRubyMapping
4
+ # PeopleProperty class
4
5
  class PeopleProperty < MultiProperty
5
6
  TYPE = "people"
7
+
8
+ # @param [String] name
9
+ # @param [Hash] json
10
+ # @param [Array] people ids for people
11
+ def initialize(name, will_update: false, json: nil, people: nil)
12
+ super name, will_update: will_update
13
+ @people = if people
14
+ Array(people).map { |uo| UserObject.user_object(uo) }
15
+ elsif json
16
+ json.map { |p| UserObject.new json: p }
17
+ else
18
+ []
19
+ end
20
+ end
21
+
22
+ # @return [Hash] created json
23
+ def property_values_json
24
+ {
25
+ @name => {
26
+ "type" => "people",
27
+ "people" => @people.map(&:property_values_json),
28
+ },
29
+ }
30
+ end
31
+
32
+ # @param [Hash] json
33
+ def update_from_json(json)
34
+ @will_update = false
35
+ @people = json["people"].map { |pjson| UserObject.new json: pjson }
36
+ end
37
+
38
+ # @param [Hash] people
39
+ # @return [Array, nil] settled array
40
+ def people=(people)
41
+ @will_update = true
42
+ @people = people ? Array(people).map { |uo| UserObject.user_object(uo) } : []
43
+ end
6
44
  end
7
45
  end
@@ -1,7 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NotionRubyMapping
4
- class PhoneNumberProperty < TextProperty
4
+ # PhoneNumberProperty
5
+ class PhoneNumberProperty < Property
6
+ include EqualsDoesNotEqual
7
+ include ContainsDoesNotContain
8
+ include StartsWithEndsWith
9
+ include IsEmptyIsNotEmpty
5
10
  TYPE = "phone_number"
11
+
12
+ # @param [String] name Property name
13
+ # @param [String] phone_number phone_number value (optional)
14
+ def initialize(name, will_update: false, phone_number: nil)
15
+ super name, will_update: will_update
16
+ @phone_number = phone_number
17
+ end
18
+ attr_reader :phone_number
19
+
20
+ # @param [Hash] json
21
+ def update_from_json(json)
22
+ @will_update = false
23
+ @phone_number = json["phone_number"]
24
+ end
25
+
26
+ # @return [Hash]
27
+ def property_values_json
28
+ {@name => {"phone_number" => @phone_number, "type" => "phone_number"}}
29
+ end
30
+
31
+ def phone_number=(phone_number)
32
+ @will_update = true
33
+ @phone_number = phone_number
34
+ end
6
35
  end
7
36
  end