notion_ruby_mapping 0.2.3 → 0.3.0

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/README.md +416 -135
  3. data/env.yml.sample +1 -0
  4. data/examples/change_title.md +26 -0
  5. data/examples/renumbering_pages.md +20 -0
  6. data/examples/set_icon_to_all_icon_unsettled_pages.md +30 -0
  7. data/lib/notion_ruby_mapping/base.rb +124 -71
  8. data/lib/notion_ruby_mapping/checkbox_property.rb +27 -12
  9. data/lib/notion_ruby_mapping/created_by_property.rb +22 -10
  10. data/lib/notion_ruby_mapping/created_time_property.rb +16 -14
  11. data/lib/notion_ruby_mapping/database.rb +74 -10
  12. data/lib/notion_ruby_mapping/date_property.rb +67 -42
  13. data/lib/notion_ruby_mapping/email_property.rb +26 -16
  14. data/lib/notion_ruby_mapping/files_property.rb +40 -24
  15. data/lib/notion_ruby_mapping/formula_property.rb +51 -10
  16. data/lib/notion_ruby_mapping/last_edited_by_property.rb +22 -9
  17. data/lib/notion_ruby_mapping/last_edited_time_property.rb +16 -14
  18. data/lib/notion_ruby_mapping/list.rb +3 -0
  19. data/lib/notion_ruby_mapping/multi_select_property.rb +83 -21
  20. data/lib/notion_ruby_mapping/notion_cache.rb +17 -13
  21. data/lib/notion_ruby_mapping/number_property.rb +71 -10
  22. data/lib/notion_ruby_mapping/page.rb +32 -10
  23. data/lib/notion_ruby_mapping/payload.rb +21 -3
  24. data/lib/notion_ruby_mapping/people_property.rb +47 -19
  25. data/lib/notion_ruby_mapping/phone_number_property.rb +26 -15
  26. data/lib/notion_ruby_mapping/property.rb +140 -49
  27. data/lib/notion_ruby_mapping/property_cache.rb +31 -3
  28. data/lib/notion_ruby_mapping/query.rb +10 -0
  29. data/lib/notion_ruby_mapping/relation_property.rb +74 -21
  30. data/lib/notion_ruby_mapping/rich_text_array.rb +81 -0
  31. data/lib/notion_ruby_mapping/rich_text_object.rb +1 -0
  32. data/lib/notion_ruby_mapping/rich_text_property.rb +12 -1
  33. data/lib/notion_ruby_mapping/rollup_property.rb +82 -10
  34. data/lib/notion_ruby_mapping/select_property.rb +88 -13
  35. data/lib/notion_ruby_mapping/text_object.rb +0 -2
  36. data/lib/notion_ruby_mapping/text_property.rb +19 -45
  37. data/lib/notion_ruby_mapping/title_property.rb +12 -1
  38. data/lib/notion_ruby_mapping/url_property.rb +26 -15
  39. data/lib/notion_ruby_mapping/user_object.rb +4 -4
  40. data/lib/notion_ruby_mapping/version.rb +1 -1
  41. data/lib/notion_ruby_mapping.rb +2 -1
  42. metadata +6 -2
data/env.yml.sample CHANGED
@@ -12,3 +12,4 @@ db_update_page: "206ffaa277744a99baf593e28730240c"
12
12
  user_hkob: "2200a911-6a96-44bb-bd38-6bfb1e01b9f6"
13
13
  parent1_page: "860753bb6d1f48de96211fa6e0e31f82"
14
14
  parent_database: "1d6b1040a9fb48d99a3d041429816e9f"
15
+ created_database: "c7697137d49f49c2bbcdd6a665c4f921"
@@ -0,0 +1,26 @@
1
+ # Change title
2
+
3
+ The following code update the page title.
4
+
5
+ #### Pattern 1 (replace existing text partially)
6
+
7
+ ```Ruby
8
+ page = Page.find page_id # API access
9
+ print page.title # -> ABC\nDEF
10
+ tp = page.properties["Title"]
11
+ tp[1].text = "GHI"
12
+ page.save # API access
13
+ print page.title # -> ABC\nGHI
14
+ ```
15
+
16
+ #### Pattern 2 (replace all text)
17
+
18
+ ```Ruby
19
+ page = Page.new id: page_id, assign: [TitleProperty, "Title"]
20
+ tp = page.properties["Title"]
21
+ tp << TextObject.new("JKL")
22
+ page.save # API access
23
+ print page.title # -> JKL
24
+ ```
25
+ ---
26
+ [Return to README.md](../README.md#2-example-code)
@@ -0,0 +1,20 @@
1
+ # Renumbering pages
2
+
3
+ The following code sets serial numbers to the pages whose title is not empty in ascending order of titles.
4
+
5
+ ```Ruby
6
+ db = Database.new id: database_id, assign: [RichTextProperty, "TextTitle"]
7
+ tp = db.properties["TextTitle"]
8
+ query = tp.filter_is_not_empty.ascending(tp)
9
+ db.query_database(tp.filter_is_not_empty.ascending(tp)).each.with_index(1) do |page, index|
10
+ page.properties["NumberTitle"].number = index
11
+ page.save
12
+ end
13
+ ```
14
+
15
+ | After execution |
16
+ |-----------------------------------------------|
17
+ | ![After exuecution](../images/serial_number.png) |
18
+
19
+ ---
20
+ [Return to README.md](../README.md#2-example-code)
@@ -0,0 +1,30 @@
1
+ # Set icon to all icon unsettled pages
2
+
3
+ The following code sets a "💿" icon on all unset pages in the database.
4
+
5
+ ```Ruby
6
+ require "notion_ruby_mapping"
7
+
8
+ include NotionRubyMapping
9
+
10
+ token = ENV["NOTION_API_TOKEN"]
11
+ database_id = ENV["DATABASE_ID"]
12
+
13
+ NotionCache.instance.create_client token
14
+
15
+ db = Database.new id: database_id
16
+ db.query_database.each do |page|
17
+ unless page.icon
18
+ page.set_icon(emoji: "💿")
19
+ page.save
20
+ p page.id
21
+ end
22
+ end
23
+ ```
24
+
25
+ |Before execution|After execution|
26
+ |---|---|
27
+ |![Before execution](../images/pre_set_icon.png)|![After execution](../images/post_set_icon.png)|
28
+
29
+ ---
30
+ [Return to README.md](../README.md#2-example-code)
@@ -3,6 +3,8 @@
3
3
  module NotionRubyMapping
4
4
  # Notion Base object (Parent of Page / Database / List)
5
5
  class Base
6
+ #### Public announced methods
7
+
6
8
  # @param [Hash, nil] json
7
9
  # @param [String, nil] id
8
10
  # @param [Array<Property, Class, String>] assign
@@ -15,31 +17,53 @@ module NotionRubyMapping
15
17
 
16
18
  @payload = Payload.new(parent && {"parent" => parent})
17
19
  @property_cache = nil
20
+ @created_time = nil
21
+ @last_edited_time = nil
18
22
  assign.each_slice(2) { |(klass, key)| assign_property(klass, key) }
19
23
  end
20
24
  attr_reader :json, :id
21
25
 
22
- # @param [Hash, Notion::Messages] json
23
- # @return [NotionRubyMapping::Base]
24
- def self.create_from_json(json)
25
- case json["object"]
26
- when "page"
27
- Page.new json: json
28
- when "database"
29
- Database.new json: json
30
- when "list"
31
- List.new json: json
32
- when "block"
33
- Block.new json: json
26
+ # @param [String] key
27
+ # @return [NotionRubyMapping::PropertyCache, Hash] obtained Page value or PropertyCache
28
+ def [](key)
29
+ unless @json
30
+ raise StandardError, "Unknown id" if @id.nil?
31
+
32
+ reload
33
+ end
34
+ case key
35
+ when "properties"
36
+ properties
34
37
  else
35
- raise StandardError, json.inspect
38
+ @json[key]
36
39
  end
37
40
  end
38
41
 
42
+ # @return [NotionRubyMapping::CreatedTimeProperty]
43
+ def created_time
44
+ @created_time ||= CreatedTimeProperty.new("title")
45
+ end
46
+
47
+ # @return [TrueClass, FalseClass] true if Database object
48
+ def database?
49
+ is_a? Database
50
+ end
51
+
52
+ # @return [Hash, nil] obtained Hash
53
+ def icon
54
+ self["icon"]
55
+ end
56
+
57
+ # @return [Boolean] true if new record
39
58
  def new_record?
40
59
  @new_record
41
60
  end
42
61
 
62
+ # @return [TrueClass, FalseClass] true if Page object
63
+ def page?
64
+ is_a? Page
65
+ end
66
+
43
67
  # @return [NotionRubyMapping::PropertyCache] get or created PropertyCache object
44
68
  def properties
45
69
  unless @property_cache
@@ -48,30 +72,68 @@ module NotionRubyMapping
48
72
 
49
73
  reload
50
74
  end
51
- @property_cache = PropertyCache.new json_properties
75
+ @property_cache = PropertyCache.new json_properties, base_type: database? ? :database : :page
52
76
  end
53
77
  @property_cache
54
78
  end
55
79
 
80
+ # @return [NotionRubyMapping::Base, String]
81
+ def save(dry_run: false)
82
+ if dry_run
83
+ @new_record ? create(dry_run: true) : update(dry_run: true)
84
+ else
85
+ @new_record ? create : update
86
+ @property_cache.clear_will_update
87
+ @payload.clear
88
+ self
89
+ end
90
+ end
91
+
92
+ # @param [String] emoji
93
+ # @param [String] url
94
+ # @return [NotionRubyMapping::Base]
95
+ def set_icon(emoji: nil, url: nil)
96
+ @payload.set_icon(emoji: emoji, url: url) if page? || database?
97
+ self
98
+ end
99
+
56
100
  # @return [String] title
57
101
  def title
58
102
  properties.select { |p| p.is_a? TitleProperty }.map(&:full_text).join ""
59
103
  end
60
104
 
61
- # @return [NotionRubyMapping::Base] reloaded self
62
- def reload
63
- update_json reload_json
64
- self
65
- end
66
-
67
- # @return [NotionRubyMapping::Base]
68
- def save
69
- @new_record ? create : update
105
+ ### Not public announced methods
106
+
107
+ # @param [Hash, Notion::Messages] json
108
+ # @return [NotionRubyMapping::Base]
109
+ def self.create_from_json(json)
110
+ case json["object"]
111
+ when "page"
112
+ Page.new json: json
113
+ when "database"
114
+ Database.new json: json
115
+ when "list"
116
+ List.new json: json
117
+ when "block"
118
+ Block.new json: json
119
+ else
120
+ raise StandardError, json.inspect
121
+ end
70
122
  end
71
123
 
72
- # @return [Hash] json properties
73
- def json_properties
74
- @json && @json["properties"]
124
+ # @param [NotionRubyMapping::Property] klass
125
+ # @param [String] title
126
+ # @return [NotionRubyMapping::Property] generated property
127
+ def assign_property(klass, title)
128
+ @property_cache ||= PropertyCache.new({}, base_type: database? ? :database : :page)
129
+
130
+ property = if database?
131
+ klass.new(title, will_update: new_record?, base_type: :database)
132
+ else
133
+ klass.new(title, will_update: true, base_type: :page)
134
+ end
135
+ @property_cache.add_property property
136
+ property
75
137
  end
76
138
 
77
139
  # @return [NotionRubyMapping::List]
@@ -79,74 +141,65 @@ module NotionRubyMapping
79
141
  @children ||= @nc.block_children(id)
80
142
  end
81
143
 
82
- # @param [Hash] json
83
- # @return [NotionRubyMapping::Base]
84
- def update_json(json)
85
- raise StandardError, json.inspect unless json["object"] != "error" && @json.nil? || @json["type"] == json["type"]
144
+ # @return [Hash] created json for update page
145
+ def property_values_json
146
+ @payload.property_values_json @property_cache
147
+ end
86
148
 
87
- @json = json
88
- @id = @nc.hex_id(@json["id"])
89
- restore_from_json
149
+ # @return [NotionRubyMapping::Base] reloaded self
150
+ def reload
151
+ update_json reload_json
90
152
  self
91
153
  end
92
154
 
155
+ # @return [NotionRubyMapping::Base]
93
156
  def restore_from_json
94
- @payload.clear
95
157
  return if (ps = @json["properties"]).nil?
96
158
 
97
159
  properties.json = json_properties
98
- return unless is_a? Page
160
+ return unless is_a?(Page) || is_a?(Database)
99
161
 
100
162
  ps.each do |key, json|
101
163
  properties[key].update_from_json json
102
164
  end
165
+ self
103
166
  end
104
167
 
105
- # @param [String] emoji
106
- # @param [String] url
168
+ # @param [Hash] json
107
169
  # @return [NotionRubyMapping::Base]
108
- def set_icon(emoji: nil, url: nil)
109
- if is_a?(Page) || is_a?(Database)
110
- @payload.set_icon(emoji: emoji, url: url)
111
- end
170
+ def update_json(json)
171
+ raise StandardError, json.inspect unless json["object"] != "error" && @json.nil? || @json["type"] == json["type"]
172
+
173
+ @json = json
174
+ @id = @nc.hex_id(@json["id"])
175
+ restore_from_json
112
176
  self
113
177
  end
114
178
 
115
- # @param [String] key
116
- # @return [NotionRubyMapping::PropertyCache, Hash] obtained Page value or PropertyCache
117
- def [](key)
118
- unless @json
119
- raise StandardError, "Unknown id" if @id.nil?
120
-
121
- reload
122
- end
123
- case key
124
- when "properties"
125
- properties
126
- else
127
- @json[key]
128
- end
179
+ # protected
180
+ # @return [Hash] json properties
181
+ def json_properties
182
+ @json && @json["properties"]
129
183
  end
130
184
 
131
- # @return [Hash, nil] obtained Hash
132
- def icon
133
- self["icon"]
185
+ # @param [Object] method
186
+ # @param [Object] path
187
+ # @param [nil] json
188
+ def self.dry_run_script(method, path, json = nil)
189
+ shell = [
190
+ "#!/bin/sh\ncurl #{method == :get ? "" : "-X #{method.to_s.upcase}"} 'https://api.notion.com/#{path}'",
191
+ " -H 'Notion-Version: 2022-02-22'",
192
+ " -H 'Authorization: Bearer '\"$NOTION_API_KEY\"''"
193
+ ]
194
+ shell << " -H 'Content-Type: application/json'" unless path == :get
195
+ shell << " --data '#{JSON.generate json}'" if json
196
+ shell.join("\\ \n")
134
197
  end
135
198
 
136
- # @param [Property, Class] klass
137
- # @param [String] title
138
- # @return [Property] generated property
139
- def assign_property(klass, title)
140
- @property_cache ||= PropertyCache.new {}
141
-
142
- property = klass.new(title, will_update: true)
143
- @property_cache.add_property property
144
- property
145
- end
199
+ protected
146
200
 
147
- # @return [Hash] created json
148
- def property_values_json
149
- @payload.property_values_json @property_cache&.property_values_json
201
+ def dry_run_script(method, path, json_method)
202
+ self.class.dry_run_script method, path, send(json_method)
150
203
  end
151
204
  end
152
205
  end
@@ -6,30 +6,45 @@ module NotionRubyMapping
6
6
  include EqualsDoesNotEqual
7
7
  TYPE = "checkbox"
8
8
 
9
- # @param [String] name Property name
10
- # @param [Boolean] checkbox Number value (optional)
11
- def initialize(name, will_update: false, checkbox: false)
12
- super name, will_update: will_update
13
- @checkbox = checkbox
9
+ ### Public announced methods
10
+
11
+ ## Common methods
12
+
13
+ # @return [Boolean, Hash]
14
+ def checkbox
15
+ @json
14
16
  end
15
- attr_reader :checkbox
17
+
18
+ ## Page property only methods
16
19
 
17
20
  # @param [Boolean] flag
18
21
  # @return [TrueClass, FalseClass] settled value
19
22
  def checkbox=(flag)
20
23
  @will_update = true
21
- @checkbox = flag
24
+ @json = flag
22
25
  end
23
26
 
24
- # @param [Hash] json
25
- def update_from_json(json)
26
- @will_update = false
27
- @checkbox = json["checkbox"]
27
+ ### Not public announced methods
28
+
29
+ ## Common methods
30
+
31
+ # @param [String] name Property name
32
+ # @param [Boolean, Hash] json
33
+ def initialize(name, will_update: false, base_type: :page, json: nil)
34
+ super name, will_update: will_update, base_type: base_type
35
+ @json = if database?
36
+ json || {}
37
+ else
38
+ json || false
39
+ end
28
40
  end
29
41
 
42
+ ## Page property only methods
43
+
30
44
  # @return [Hash]
31
45
  def property_values_json
32
- {@name => {"checkbox" => @checkbox, "type" => "checkbox"}}
46
+ assert_page_property __method__
47
+ {@name => {"checkbox" => @json, "type" => "checkbox"}}
33
48
  end
34
49
  end
35
50
  end
@@ -5,24 +5,36 @@ module NotionRubyMapping
5
5
  class CreatedByProperty < MultiProperty
6
6
  TYPE = "created_by"
7
7
 
8
+ ### Public announced methods
9
+
10
+ ## Common methods
11
+
12
+ # @return [NotionRubyMapping::UserObject, Hash]
13
+ def created_by
14
+ @json
15
+ end
16
+
17
+ ### Not public announced methods
18
+
19
+ ## Common methods
20
+
8
21
  # @param [String] name Property name
9
22
  # @param [String] user_id user_id (optional)
10
23
  # @param [Hash] json json (optional)
11
- def initialize(name, json: nil, user_id: nil)
12
- super name, will_update: false
13
- @user = UserObject.new user_id: user_id, json: json
24
+ def initialize(name, will_update: false, base_type: :page, json: nil, user_id: nil)
25
+ super name, will_update: will_update, base_type: base_type
26
+ @json = if database?
27
+ json || {}
28
+ else
29
+ UserObject.new user_id: user_id, json: json
30
+ end
14
31
  end
15
- attr_reader :user
16
32
 
17
33
  # @param [Hash] json
18
34
  def update_from_json(json)
19
35
  @will_update = false
20
- @user = UserObject.new json: json["created_by"]
21
- end
22
-
23
- # @return [Hash] {} created_time cannot be updated
24
- def property_values_json
25
- {}
36
+ cb = json["created_by"]
37
+ @json = database? ? cb : UserObject.new(json: cb)
26
38
  end
27
39
  end
28
40
  end
@@ -5,23 +5,25 @@ module NotionRubyMapping
5
5
  class CreatedTimeProperty < DateBaseProperty
6
6
  TYPE = "created_time"
7
7
 
8
- # @param [String] name Property name
9
- # @param [String] created_time created_time value (optional)
10
- def initialize(name, created_time: nil)
11
- super name, will_update: false
12
- @created_time = created_time
13
- end
14
- attr_reader :created_time
8
+ ### Public announced methods
9
+
10
+ ## Common methods
15
11
 
16
- # @param [Hash] json
17
- def update_from_json(json)
18
- @will_update = false
19
- @created_time = json["created_time"]
12
+ # @return [Date, Hash]
13
+ def created_time
14
+ @json
20
15
  end
21
16
 
22
- # @return [Hash] {} created_time cannot be updated
23
- def property_values_json
24
- {}
17
+ ### Not public announced methods
18
+
19
+ ## Common methods
20
+
21
+ # @param [String] name Property name
22
+ # @param [String] json created_time value (optional)
23
+ def initialize(name, will_update: false, base_type: :page, json: nil)
24
+ super name, will_update: will_update, base_type: base_type
25
+ @json = json
26
+ @json ||= {} if database?
25
27
  end
26
28
  end
27
29
  end
@@ -3,19 +3,28 @@
3
3
  module NotionRubyMapping
4
4
  # Notion database
5
5
  class Database < Base
6
- def self.find(id)
7
- NotionCache.instance.database id
8
- end
6
+ ### Public announced methods
9
7
 
10
- # @param [NotionRubyMapping::Query] query object
11
- def query_database(query = Query.new)
12
- response = @nc.database_query @id, query
13
- List.new json: response, database: self, query: query
8
+ # @param [String] id
9
+ # @return [NotionRubyMapping::Database, String]
10
+ def self.find(id, dry_run: false)
11
+ nc = NotionCache.instance
12
+ if dry_run
13
+ dry_run_script :get, nc.database_path(id)
14
+ else
15
+ nc.database id
16
+ end
14
17
  end
15
18
 
16
- # @return [NotionRubyMapping::Base]
17
- def update
18
- update_json @nc.update_database_request(@id, property_values_json)
19
+ # @return [NotionRubyMapping::Property]
20
+ # @param [Class] klass
21
+ # @param [String] title
22
+ def add_property(klass, title)
23
+ prop = assign_property klass, title
24
+ yield prop if block_given?
25
+ @payload.merge_property prop.property_schema_json
26
+ prop.clear_will_update
27
+ prop
19
28
  end
20
29
 
21
30
  # @param [Array<Property, Class, String>] assign
@@ -24,11 +33,66 @@ module NotionRubyMapping
24
33
  Page.new assign: assign, parent: {"database_id" => @id}
25
34
  end
26
35
 
36
+ # @return [NotionRubyMapping::RichTextArray]
37
+ def database_title
38
+ @database_title ||= RichTextArray.new "title", json: (self["title"]), will_update: new_record?
39
+ end
40
+
41
+ def property_schema_json
42
+ @payload.property_schema_json @property_cache, database_title
43
+ end
44
+
45
+ # @return [Hash] created json for update database
46
+ def property_values_json
47
+ @payload.property_values_json @property_cache, database_title
48
+ end
49
+
50
+ # @param [NotionRubyMapping::Query] query object
51
+ # @return [NotionRubyMapping::List, String]
52
+ def query_database(query = Query.new, dry_run: false)
53
+ if dry_run
54
+ Base.dry_run_script :post, @nc.query_database_path(@id), query.query_json
55
+ else
56
+ response = @nc.database_query @id, query
57
+ List.new json: response, database: self, query: query
58
+ end
59
+ end
60
+
61
+ # @param [Array] names
62
+ # @return [Array<NotionRubyMapping::Property>]
63
+ def remove_properties(*names)
64
+ names.map { |n| properties[n] }.each(&:remove)
65
+ end
66
+
67
+ # @return [Hash] created json for update database
68
+ def update_property_schema_json
69
+ @payload.update_property_schema_json @property_cache, database_title
70
+ end
71
+
27
72
  protected
28
73
 
74
+ def create(dry_run: false)
75
+ if dry_run
76
+ dry_run_script :post, @nc.databases_path, :property_schema_json
77
+ else
78
+ json = @nc.create_database_request(property_schema_json)
79
+ @new_record = false
80
+ update_json json
81
+ end
82
+ end
83
+
29
84
  # @return [Hash]
30
85
  def reload_json
31
86
  @nc.database_request @id
32
87
  end
88
+
89
+ # @return [NotionRubyMapping::Base, String]
90
+ def update(dry_run: false)
91
+ if dry_run
92
+ dry_run_script :patch, @nc.database_path(@id), :update_property_schema_json
93
+ else
94
+ update_json @nc.update_database_request(@id, update_property_schema_json)
95
+ end
96
+ end
33
97
  end
34
98
  end