notion_ruby_mapping 0.1.4 → 0.2.2

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 +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