notion_ruby_mapping 0.2.1 → 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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +500 -141
  3. data/env.yml.sample +2 -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 +130 -73
  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 +78 -8
  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 +27 -19
  19. data/lib/notion_ruby_mapping/mention_object.rb +26 -1
  20. data/lib/notion_ruby_mapping/multi_select_property.rb +83 -21
  21. data/lib/notion_ruby_mapping/notion_cache.rb +25 -10
  22. data/lib/notion_ruby_mapping/number_property.rb +71 -10
  23. data/lib/notion_ruby_mapping/page.rb +33 -5
  24. data/lib/notion_ruby_mapping/payload.rb +23 -5
  25. data/lib/notion_ruby_mapping/people_property.rb +47 -19
  26. data/lib/notion_ruby_mapping/phone_number_property.rb +26 -15
  27. data/lib/notion_ruby_mapping/property.rb +140 -49
  28. data/lib/notion_ruby_mapping/property_cache.rb +31 -3
  29. data/lib/notion_ruby_mapping/query.rb +10 -0
  30. data/lib/notion_ruby_mapping/relation_property.rb +74 -21
  31. data/lib/notion_ruby_mapping/rich_text_array.rb +81 -0
  32. data/lib/notion_ruby_mapping/rich_text_object.rb +58 -1
  33. data/lib/notion_ruby_mapping/rich_text_property.rb +12 -1
  34. data/lib/notion_ruby_mapping/rollup_property.rb +82 -10
  35. data/lib/notion_ruby_mapping/select_property.rb +88 -13
  36. data/lib/notion_ruby_mapping/text_object.rb +0 -51
  37. data/lib/notion_ruby_mapping/text_property.rb +19 -45
  38. data/lib/notion_ruby_mapping/title_property.rb +12 -1
  39. data/lib/notion_ruby_mapping/url_property.rb +26 -15
  40. data/lib/notion_ruby_mapping/user_object.rb +4 -4
  41. data/lib/notion_ruby_mapping/version.rb +1 -1
  42. data/lib/notion_ruby_mapping.rb +2 -1
  43. data/tools/an +103 -0
  44. metadata +7 -2
data/env.yml.sample CHANGED
@@ -11,3 +11,5 @@ db_second_page: "6601e719a39a460c908e8909467fcccf"
11
11
  db_update_page: "206ffaa277744a99baf593e28730240c"
12
12
  user_hkob: "2200a911-6a96-44bb-bd38-6bfb1e01b9f6"
13
13
  parent1_page: "860753bb6d1f48de96211fa6e0e31f82"
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,41 +3,65 @@
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
9
- def initialize(json: nil, id: nil, assign: [])
11
+ def initialize(json: nil, id: nil, assign: [], parent: nil)
10
12
  @nc = NotionCache.instance
11
13
  @json = json
12
14
  @id = @nc.hex_id(id || json && @json["id"])
13
- raise StandardError, "Unknown id" if !is_a?(List) && @id.nil?
15
+ @new_record = true unless parent.nil?
16
+ raise StandardError, "Unknown id" if !is_a?(List) && @id.nil? && parent.nil?
14
17
 
15
- @payload = nil
18
+ @payload = Payload.new(parent && {"parent" => parent})
16
19
  @property_cache = nil
20
+ @created_time = nil
21
+ @last_edited_time = nil
17
22
  assign.each_slice(2) { |(klass, key)| assign_property(klass, key) }
18
23
  end
19
24
  attr_reader :json, :id
20
25
 
21
- # @param [Hash, Notion::Messages] json
22
- # @return [NotionRubyMapping::Base]
23
- def self.create_from_json(json)
24
- case json["object"]
25
- when "page"
26
- Page.new json: json
27
- when "database"
28
- Database.new json: json
29
- when "list"
30
- List.new json: json
31
- when "block"
32
- 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
33
37
  else
34
- raise StandardError, json.inspect
38
+ @json[key]
35
39
  end
36
40
  end
37
41
 
38
- # @return [NotionRubyMapping::Payload] get or created Payload object
39
- def payload
40
- @payload ||= Payload.new
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
58
+ def new_record?
59
+ @new_record
60
+ end
61
+
62
+ # @return [TrueClass, FalseClass] true if Page object
63
+ def page?
64
+ is_a? Page
41
65
  end
42
66
 
43
67
  # @return [NotionRubyMapping::PropertyCache] get or created PropertyCache object
@@ -48,25 +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
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
65
122
  end
66
123
 
67
- # @return [Hash] json properties
68
- def json_properties
69
- @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
70
137
  end
71
138
 
72
139
  # @return [NotionRubyMapping::List]
@@ -74,75 +141,65 @@ module NotionRubyMapping
74
141
  @children ||= @nc.block_children(id)
75
142
  end
76
143
 
77
- # @param [Hash] json
78
- # @return [NotionRubyMapping::Base]
79
- def update_json(json)
80
- 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
81
148
 
82
- @json = json
83
- @id = @nc.hex_id(@json["id"])
84
- restore_from_json
149
+ # @return [NotionRubyMapping::Base] reloaded self
150
+ def reload
151
+ update_json reload_json
85
152
  self
86
153
  end
87
154
 
155
+ # @return [NotionRubyMapping::Base]
88
156
  def restore_from_json
89
- payload.clear
90
157
  return if (ps = @json["properties"]).nil?
91
158
 
92
159
  properties.json = json_properties
93
- return unless is_a? Page
160
+ return unless is_a?(Page) || is_a?(Database)
94
161
 
95
162
  ps.each do |key, json|
96
163
  properties[key].update_from_json json
97
164
  end
165
+ self
98
166
  end
99
167
 
100
- # @param [String] emoji
101
- # @param [String] url
168
+ # @param [Hash] json
102
169
  # @return [NotionRubyMapping::Base]
103
- def set_icon(emoji: nil, url: nil)
104
- if is_a?(Page) || is_a?(Database)
105
- payload.set_icon(emoji: emoji, url: url)
106
- update
107
- 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
108
176
  self
109
177
  end
110
178
 
111
- # @param [String] key
112
- # @return [NotionRubyMapping::PropertyCache, Hash] obtained Page value or PropertyCache
113
- def [](key)
114
- unless @json
115
- raise StandardError, "Unknown id" if @id.nil?
116
-
117
- reload
118
- end
119
- case key
120
- when "properties"
121
- properties
122
- else
123
- @json[key]
124
- end
179
+ # protected
180
+ # @return [Hash] json properties
181
+ def json_properties
182
+ @json && @json["properties"]
125
183
  end
126
184
 
127
- # @return [Hash, nil] obtained Hash
128
- def icon
129
- 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")
130
197
  end
131
198
 
132
- # @param [Property, Class] klass
133
- # @param [String] title
134
- # @return [Property] generated property
135
- def assign_property(klass, title)
136
- @property_cache ||= PropertyCache.new {}
137
-
138
- property = klass.new(title, will_update: true)
139
- @property_cache.add_property property
140
- property
141
- end
199
+ protected
142
200
 
143
- # @return [Hash] created json
144
- def property_values_json
145
- 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)
146
203
  end
147
204
  end
148
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,26 +3,96 @@
3
3
  module NotionRubyMapping
4
4
  # Notion database
5
5
  class Database < Base
6
- def self.find(id)
7
- NotionCache.instance.database id
6
+ ### Public announced methods
7
+
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
8
17
  end
9
18
 
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
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
14
28
  end
15
29
 
30
+ # @param [Array<Property, Class, String>] assign
16
31
  # @return [NotionRubyMapping::Base]
17
- def update
18
- update_json @nc.update_database_request(@id, property_values_json)
32
+ def create_child_page(*assign)
33
+ Page.new assign: assign, parent: {"database_id" => @id}
34
+ end
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
19
70
  end
20
71
 
21
72
  protected
22
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
+
23
84
  # @return [Hash]
24
85
  def reload_json
25
86
  @nc.database_request @id
26
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
27
97
  end
28
98
  end