notion_ruby_mapping 0.1.4 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Guardfile +1 -1
  3. data/README.md +514 -267
  4. data/env.yml.sample +8 -0
  5. data/lib/notion_ruby_mapping/base.rb +47 -36
  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 +14 -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 +46 -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 +137 -53
  21. data/lib/notion_ruby_mapping/number_property.rb +13 -8
  22. data/lib/notion_ruby_mapping/page.rb +11 -2
  23. data/lib/notion_ruby_mapping/payload.rb +12 -4
  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,56 @@ 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
+ @load_all_contents = !@has_more
12
+ @database = database
13
+ @query = query
14
+ @index = 0
15
+ @has_content = true
16
+ end
17
+ attr_reader :has_more
18
+
8
19
  def each
9
20
  return enum_for(:each) unless block_given?
10
21
 
11
- json["results"].each do |block_json|
12
- yield Base.create_from_json(block_json)
22
+ if @database
23
+ unless @has_content # re-exec
24
+ unless @load_all_contents
25
+ @query.start_cursor = nil
26
+ @json = @database.query_database @query
27
+ @has_more = @json["has_more"]
28
+ end
29
+ @index = 0
30
+ @has_content = true
31
+ end
32
+
33
+ while @has_content
34
+ if @index < results.length
35
+ object = Base.create_from_json(results[@index])
36
+ @index += 1
37
+ yield object
38
+ elsif @has_more
39
+ if @database
40
+ @query.start_cursor = @json["next_cursor"]
41
+ @json = @database.query_database @query
42
+ @index = 0
43
+ @has_more = @json["has_more"]
44
+ else
45
+ @has_content = false
46
+ end
47
+ else
48
+ @has_content = false
49
+ end
50
+ end
13
51
  end
14
52
  end
53
+
54
+ private
55
+
56
+ def results
57
+ @json["results"]
58
+ end
15
59
  end
16
60
  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,140 @@
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
+ # @return [String (frozen)] page_path
46
+ def pages_path
47
+ "v1/pages"
48
+ end
49
+
50
+ # @param [String] database_id
51
+ # @return [String (frozen)] page_path
52
+ def database_path(database_id)
53
+ "v1/databases/#{database_id}"
54
+ end
55
+
56
+ # @param [String] block_id
57
+ # @return [String (frozen)] page_path
58
+ def block_path(block_id)
59
+ "v1/blocks/#{block_id}"
60
+ end
61
+
62
+ # @param [String] database_id
63
+ # @return [String (frozen)] page_path
64
+ def query_database_path(database_id)
65
+ "v1/databases/#{database_id}/query"
66
+ end
67
+
68
+ ### Notion API call
69
+
70
+ # @param [Symbol] method
71
+ # @param [String] path
72
+ # @param [Hash] options
73
+ # @return [Hash] response hash
74
+ def request(method, path, options = {})
75
+ raise "Please call `NotionCache.create_client' before using other methods" unless @notion_token
76
+
77
+ sleep @wait
78
+ response = @client.send(method) do |request|
79
+ request.headers["Authorization"] = "Bearer #{@notion_token}"
80
+ request.headers["Notion-Version"] = NotionRubyMapping::NOTION_VERSION
81
+ case method
82
+ when :get, :delete
83
+ request.url path, options
84
+ when :post, :put, :patch
85
+ request.headers["Content-Type"] = "application/json"
86
+ request.path = path
87
+ request.body = options.to_json unless options.empty?
88
+ else
89
+ raise StandardError, "Unknown method: #{method}"
90
+ end
91
+ request.options.merge!(options.delete(:request)) if options.key? :request
92
+ end
93
+ p response.body if @debug
94
+ response.body
95
+ end
96
+
97
+ # @param [String] page_id
98
+ # @return [Hash] response
99
+ def page_request(page_id)
100
+ request :get, page_path(page_id)
101
+ end
102
+
103
+ # @param [String] database_id
104
+ # @return [Hash] response
105
+ def database_request(database_id)
106
+ request :get, database_path(database_id)
107
+ end
108
+
109
+ def database_query_request(database_id, payload)
110
+ request :post, "v1/databases/#{database_id}/query", payload
111
+ end
112
+
113
+ # @param [String] block_id
114
+ # @return [Hash] response
115
+ def block_request(block_id)
116
+ request :get, block_path(block_id)
117
+ end
118
+
119
+ # @param [String] database_id
120
+ # @return [Hash] response
121
+ def update_database_request(database_id, payload)
122
+ request :patch, "v1/databases/#{database_id}", payload
123
+ end
124
+
125
+ # @param [String] page_id
126
+ # @param [Hash] payload
127
+ # @return [Hash] response
128
+ def update_page_request(page_id, payload)
129
+ request :patch, "v1/pages/#{page_id}", payload
130
+ end
131
+
132
+ # @param [Hash] payload
133
+ # @return [Hash] response
134
+ def create_page_request(payload)
135
+ request :post, "v1/pages", payload
136
+ end
137
+
26
138
  # @param [String] id id string with "-"
27
139
  # @return [String] id without "-"
28
140
  def hex_id(id)
@@ -30,59 +142,35 @@ module NotionRubyMapping
30
142
  end
31
143
 
32
144
  # @param [String] id id (with or without "-")
33
- # @return [NotionRubyMapping::Block, NotionRubyMapping::List, NotionRubyMapping::Database, NotionRubyMapping::Page, nil]
145
+ # @return [NotionRubyMapping::Base]
34
146
  def object_for_key(id)
35
147
  key = hex_id(id)
36
148
  return @object_hash[key] if @object_hash.key? key
37
149
 
38
- begin
39
- json = yield(@client)
40
- @object_hash[key] = Base.create_from_json json
41
- rescue StandardError
42
- nil
43
- end
150
+ json = yield(@client)
151
+ @object_hash[key] = Base.create_from_json json
44
152
  end
45
153
 
46
154
  # @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
51
- end
52
-
53
- # @param [String] id page_id (with or without "-")
54
- # @return [NotionRubyMapping::Page, nil] Page object or nil
155
+ # @return [NotionRubyMapping::Base] Page object or nil
55
156
  def page(id)
56
- object_for_key(id) { page_json id }
157
+ object_for_key(id) { page_request id }
57
158
  end
58
159
 
59
160
  # @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
161
+ # @return [NotionRubyMapping::Base] Database object or nil
68
162
  def database(id)
69
- object_for_key(id) { database_json id }
163
+ object_for_key(id) { database_request id }
70
164
  end
71
165
 
72
166
  # @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
167
+ # @return [NotionRubyMapping::Base] Block object or nil
80
168
  def block(id)
81
- object_for_key(id) { block_json id }
169
+ object_for_key(id) { block_request id }
82
170
  end
83
171
 
84
172
  # @param [String] id page_id / block_id (with or without "-")
85
- # @return [NotionRubyMapping::List] List object
173
+ # @return [NotionRubyMapping::Base] List object
86
174
  def block_children(id)
87
175
  array = []
88
176
  sleep @wait
@@ -94,24 +182,15 @@ module NotionRubyMapping
94
182
 
95
183
  # @param [String] id page_id / block_id (with or without "-")
96
184
  # @param [NotionRubyMapping::Query] query query object
97
- # @return [NotionRubyMapping::List] List object
185
+ # @return [NotionRubyMapping::Base] List object
98
186
  def database_query(id, query)
99
- array = []
100
- parameters = {database_id: id, sleep_interval: @wait, max_retries: 20}
187
+ parameters = {}
101
188
  parameters[:filter] = query.filter unless query.filter.empty?
102
189
  parameters[:sorts] = query.sort unless query.sort.empty?
190
+ parameters[:start_cursor] = query.start_cursor if query.start_cursor
191
+ parameters[:page_size] = query.page_size if query.page_size
103
192
 
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})
193
+ Base.create_from_json database_query_request(id, parameters)
115
194
  end
116
195
 
117
196
  # @param [String] id page_id (with or without "-")
@@ -120,5 +199,10 @@ module NotionRubyMapping
120
199
  sleep @wait
121
200
  @client.update_database payload.merge({database_id: id})
122
201
  end
202
+
203
+ # @return [Hash]
204
+ def clear_object_hash
205
+ @object_hash = {}
206
+ end
123
207
  end
124
208
  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,22 @@ module NotionRubyMapping
7
7
  NotionCache.instance.page id
8
8
  end
9
9
 
10
+ # @return [NotionRubyMapping::Base]46G
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
+ # @return [NotionRubyMapping::Base]
16
+ def create
17
+ @new_record = false
18
+ update_json @nc.create_page_request(property_values_json)
19
+ end
20
+
21
+ protected
22
+
14
23
  # @return [Hash]
15
24
  def reload_json
16
- @nc.page_json @id
25
+ @nc.page_request @id
17
26
  end
18
27
  end
19
28
  end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NotionRubyMapping
4
+ # Payload class
2
5
  class Payload
3
- def initialize
4
- @json = {}
6
+ def initialize(json)
7
+ @json = json || {}
5
8
  end
6
9
 
7
10
  # @param [String] emoji
@@ -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