grist 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39f012eef707967404efdc81c5d8c365ab864cde60ad40d109ba81848919822f
4
- data.tar.gz: 5422d8f6c9d779567c391914b1916e64b66f8022c8f1c15bd31848f0080de8d8
3
+ metadata.gz: 294b7958d818a5594d09d7f87847e50c0d58bf4d8056693cbb89b4f83be35cc7
4
+ data.tar.gz: 903319626e595ac69d98cfd35762ec17bd5ff266817eb607139a7e8baed16f3b
5
5
  SHA512:
6
- metadata.gz: 53f7bf3d3ff45a419329b66f77f954d0c55670f16601e8454a529545cb4efb9a55c1e6c4da56bb02960913cd982d8a02218d84ee7fc40f00c4324ae2fd8b4aba
7
- data.tar.gz: a772bed11723e68103740ef2df5771922753c0d9ef35f41d7d7c95f536950cff0b3798be5b53d3491815f0adb7b8befaa53a168b598112ebe859fe4e084eab55
6
+ metadata.gz: d252f900b40170b0e939ad50b8f8f88bcafe937a6c9ad1056d13a332d662de18e70d0e896b28a1e87d2c6f4c2a60f09a52b7be0ab94f971017f1e8c16210cf77
7
+ data.tar.gz: 8f9b32899648337b388cdb9894ac78d852c98edb5f21fbcbded7559e7f9ffb4ee57ada91455dc5fc69c66e670be9d722f4014dc4c778e5ab52255a7807cb35ec
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.7.5
1
+ 3.2.0
data/README.md CHANGED
@@ -1,38 +1,68 @@
1
- # Grist
1
+ # Grist::Ruby
2
2
 
3
- Grist ruby library to interact with Grist API.
3
+ This gem provides a Ruby client for the Grist API.
4
+
5
+ ⚠️ Library isn't ready to use, not actively maintained
4
6
 
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
8
10
 
9
11
  ```ruby
10
- gem "grist", git: "https://github.com/quentinchampenois/grist.git"
12
+ gem 'grist'
11
13
  ```
12
14
 
13
- _First release will be published on RubyGems_
15
+ And install the gem:
16
+
17
+ ```bash
18
+ $ bundle install
19
+ ```
14
20
 
15
- ## Examples
21
+ ## Usage
16
22
 
17
- List all organizations
23
+ See `examples/main.rb` for some examples, here is how to use them:
18
24
 
19
- ```ruby
20
- require "faraday"
21
- require "grist"
25
+ * First example will create 1 Workspace, with 2 Documents, with 3 tables into document 'demo'.
26
+ how to use it
27
+ ```bash
28
+ $ GRIST_API_KEY=<GRIST_API_KEY> GRIST_API_URL=http://localhost:8484/api bundle exec examples/main.r
29
+ ```
30
+
31
+ * `GRIST_API_URL` base url must contain `/api`
22
32
 
23
- client = Grist::Client.new(url: "http://localhost:8484", token: "API_TOKEN")
24
- puts client.organizations
33
+ * Second example will update records
34
+ ```bash
35
+ GRIST_ORG_NAME=<ORGANIZATION_NAME> GRIST_API_KEY=<GRIST_API_KEY> GRIST_API_URL=http://localhost:8484/api bundle exec examples/update.rb
25
36
  ```
26
37
 
38
+ * `ORGANIZATION_NAME` is case-sensitive
39
+
40
+
27
41
  ## Development
28
42
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
43
+ 1. Start a Grist instance locally
44
+ ```bash
45
+ $ docker compose up -d
46
+ ```
47
+
48
+ ### Playground using IRB
49
+ Then start the ruby console
50
+ ```
51
+ $ GRIST_API_KEY=<GRIST_API_KEY> GRIST_API_URL=http://localhost:8484/api bundle exec bin/console
52
+ ```
53
+ * GRIST_API_KEY can be found directly into your account at : http://localhost:8484/o/docs/account
54
+
55
+ You can now interact with Grist, example : `$ Grist::Type::Organization.all`
56
+
57
+ ## Push a new release to RubyGems
58
+
59
+ To install this gem onto your local machine, run `bundle exec rake install`.
30
60
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
61
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
62
 
33
63
  ## Contributing
34
64
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/quentinchampenois/grist.
65
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/grist-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/grist-ruby/blob/main/CODE_OF_CONDUCT.md).
36
66
 
37
67
  ## License
38
68
 
@@ -40,4 +70,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
40
70
 
41
71
  ## Code of Conduct
42
72
 
43
- Everyone interacting in the Grist project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/grist/blob/main/CODE_OF_CONDUCT.md).
73
+ Everyone interacting in the Grist::Ruby project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/grist-ruby/blob/main/CODE_OF_CONDUCT.md).
@@ -0,0 +1,11 @@
1
+ version: '3'
2
+
3
+ services:
4
+ app:
5
+ image: gristlabs/grist:latest
6
+ ports:
7
+ - "8484:8484"
8
+ volumes:
9
+ - ./volumes/data:/persist:rw
10
+ environment:
11
+ - GRIST_SESSION_SECRET=secret
data/examples/main.rb ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "grist"
6
+ require "byebug"
7
+
8
+ raise ArgumentError, "You must provide env var : 'GRIST_API_KEY'" if ENV.fetch("GRIST_API_KEY", "").empty?
9
+ raise ArgumentError, "You must provide env var : 'GRIST_API_URL'" if ENV.fetch("GRIST_API_URL", "").empty?
10
+
11
+ orgs = Grist::Type::Organization.all
12
+ org = orgs.last
13
+
14
+ if org.nil?
15
+ puts "No organization present"
16
+ exit 0
17
+ end
18
+
19
+ puts "Org: #{org.name} - ID: #{org.id}"
20
+
21
+ ws_name = "Workspace N°#{rand(1_000)}"
22
+ puts "Creating workspace #{ws_name}..."
23
+ ws = org.create_workspace({ name: ws_name })
24
+
25
+ puts "Creating document 'demo' into workspace '#{ws_name}'..."
26
+ doc = ws.create_doc({
27
+ name: "Demo",
28
+ isPinned: true
29
+ })
30
+
31
+ puts "Creating document 'Github' into workspace '#{ws_name}'"
32
+ ws.create_doc({
33
+ name: "Github",
34
+ isPinned: false
35
+ })
36
+
37
+ puts "Creating tables for document 'demo' into workspace '#{ws_name}'..."
38
+ doc.create_tables({
39
+ "tables" => [
40
+ { "id" => "Community gems",
41
+ "columns" => [
42
+ { "id" => "name", "fields" => { "label" => "Gem name" } },
43
+ { "id" => "description", "fields" => { "label" => "Description" } },
44
+ { "id" => "link", "fields" => { "label" => "RubyGems link" } }
45
+ ] }
46
+ ]
47
+ })
48
+
49
+ puts "Creating tables for document 'demo' into workspace '#{ws_name}'..."
50
+ doc.create_tables({
51
+ "tables" => [
52
+ { "id" => "Standard library",
53
+ "columns" => [
54
+ { "id" => "name", "fields" => { "label" => "Library name" } },
55
+ { "id" => "url", "fields" => { "label" => "Source code public URL" } },
56
+ { "id" => "version", "fields" => { "label" => "Latest version" } }
57
+ ] }
58
+ ]
59
+ })
60
+
61
+ doc = ws.docs.first
62
+ tables = doc.tables
63
+
64
+ puts "Tables:"
65
+ tables.each do |table|
66
+ puts table.id
67
+ puts "Total records : #{table.records.count}"
68
+ end
69
+
70
+ table = tables.last
71
+
72
+ puts "Creating records into table from doc 'demo' into workspace '#{ws_name}'..."
73
+ table.create_records("records" => [
74
+ {
75
+ "fields" => {
76
+ "name" => "did_you_mean",
77
+ "url" => "https://github.com/ruby/did_you_mean",
78
+ "version" => "v2.0.0"
79
+ }
80
+ }
81
+ ])
82
+
83
+ puts "Terminated, go check at http://localhost:8484/o/demo"
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "grist"
6
+ require "byebug"
7
+
8
+ raise ArgumentError, "You must provide env var : 'GRIST_API_KEY'" if ENV.fetch("GRIST_API_KEY", "").empty?
9
+ raise ArgumentError, "You must provide env var : 'GRIST_API_URL'" if ENV.fetch("GRIST_API_URL", "").empty?
10
+
11
+ TABLE_NAME = "Open_source_software"
12
+
13
+ org_name = ENV.fetch("GRIST_ORG_NAME", "")
14
+ orgs = Grist::Type::Organization.all
15
+ org = orgs.find { |org| org.name == org_name }
16
+
17
+ if org&.workspaces&.empty?
18
+ puts "No workspaces found in organization #{org.name}. Creating a new one..."
19
+ ws = org.create_workspace({ name: "Grist Ruby" })
20
+ puts "Workspace created: #{ws.name} - ID: #{ws.id}"
21
+ else
22
+ ws = org&.workspaces&.last
23
+ puts "Workspaces found in organization #{org.name}. Using the last one '#{ws.name}'..."
24
+ end
25
+
26
+ puts "Workspace ID: #{ws.id}"
27
+ puts "Workspace Name: #{ws.name}"
28
+
29
+ if ws.docs.empty?
30
+ puts "No docs found in workspace #{ws.name}. Creating a new one..."
31
+ doc = ws.create_doc({ name: "Getting started" })
32
+ puts "Doc created: #{doc.name} - ID: #{doc.id}"
33
+ else
34
+ doc = ws.docs.last
35
+ puts "Docs found in workspace #{ws.name}. Using the last one '#{doc.name}'..."
36
+ end
37
+
38
+ puts "Doc ID: #{doc.id}"
39
+ puts "Doc Name: #{doc.name}"
40
+
41
+ table = doc.tables.find { |t| t.id == TABLE_NAME }
42
+ if !table.nil?
43
+ puts "Table found in doc #{doc.name}. Using the last one '#{table.id}'..."
44
+ puts "Table ID: #{table.id}"
45
+ else
46
+ puts "No tables found in doc #{doc.name}. Creating a new one..."
47
+ new_table = Grist::Type::Table.new("id" => TABLE_NAME, "columns" => [
48
+ { "id" => "name", "fields" => { "label" => "Software name" } },
49
+ { "id" => "description", "fields" => { "label" => "Description" } },
50
+ { "id" => "link", "fields" => { "label" => "Source code link" } }
51
+ ])
52
+ table = doc.create_tables("tables" => [new_table.to_hash])[0]
53
+ puts "Table created ID: #{table&.id}"
54
+ end
55
+
56
+ # TODO: WIP
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grist
4
+ module Accessible
5
+ def access
6
+ id = instance_variable_get("@id")
7
+ request(:get, "#{path}/#{id}/access")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grist
4
+ module ApiRoutes
5
+ ### ORGANIZATIONS
6
+ ORG_ALL = "https://{gristhost}/api/orgs"
7
+ ORG_FIND = "https://{gristhost}/api/orgs/{orgId}"
8
+ ORG_UPDATE = "https://{gristhost}/api/orgs/{orgId}"
9
+ ORG_DELETE = "https://{gristhost}/api/orgs/{orgId}"
10
+ # ORG ACCESS
11
+ ORG_ACCESS_ALL = "https://{gristhost}/api/orgs/{orgId}/access"
12
+ ORG_ACCESS_UPDATE = "https://{gristhost}/api/orgs/{orgId}/access"
13
+ # ORG WORKSPACE
14
+ WORKSPACE_ALL = "https://{gristhost}/api/orgs/{orgId}/workspaces"
15
+ WORKSPACE_CREATE = "https://{gristhost}/api/orgs/{orgId}/workspaces"
16
+
17
+ ### WORKSPACES
18
+ WORKSPACE_FIND = "https://{gristhost}/api/workspaces/{workspaceId}"
19
+ WORKSPACE_UPDATE = "https://{gristhost}/api/workspaces/{workspaceId}"
20
+ WORKSPACE_DELETE = "https://{gristhost}/api/workspaces/{workspaceId}"
21
+ # WORKSPACE ACCESS
22
+ WORKSPACE_ACCESS_ALL = "https://{gristhost}/api/workspaces/{orgId}/access"
23
+ WORKSPACE_ACCESS_UPDATE = "https://{gristhost}/api/workspaces/{orgId}/access"
24
+ # WORKSPACE DOCUMENTS
25
+ DOC_CREATE = "https://{gristhost}/api/workspaces/{workspaceId}/docs"
26
+
27
+ ### DOCUMENTS
28
+ DOC_FIND = "https://{gristhost}/api/docs/{docId}"
29
+ DOC_UPDATE = "https://{gristhost}/api/docs/{docId}"
30
+ DOC_DELETE = "https://{gristhost}/api/docs/{docId}"
31
+ DOC_MOVE = "https://{gristhost}/api/docs/{docId}/move"
32
+ # DOC ACCESS
33
+ DOC_ACCESS_ALL = "https://{gristhost}/api/docs/{docId}/access"
34
+ DOC_ACCESS_UPDATE = "https://{gristhost}/api/docs/{docId}/access"
35
+ # DOC ACCESS
36
+ DOC_DL_SQL = "https://{gristhost}/api/docs/{docId}/download"
37
+ DOC_DL_EXCEL = "https://{gristhost}/api/docs/{docId}/download/xlsx"
38
+ DOC_DL_CSV = "https://{gristhost}/api/docs/{docId}/download/csv"
39
+ DOC_DL_TABLE_SCHEMA = "https://{gristhost}/api/docs/{docId}/download/table-schema"
40
+ DOC_TRUNCATE_HISTORY = "https://{gristhost}/api/docs/{docId}/states/remove"
41
+ DOC_FORCE_RELOAD = "https://{gristhost}/api/docs/{docId}/force-reload"
42
+ DOC_CLEAR_QUEUE = "https://{gristhost}/api/docs/{docId}/webhooks/queue"
43
+
44
+ ### RECORDS
45
+ RECORD_ALL = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/records"
46
+ RECORD_CREATE = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/records"
47
+ RECORD_UPDATE = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/records"
48
+ RECORD_ADD_OR_UPDATE = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/records"
49
+
50
+ ### TABLES
51
+ TABLE_ALL = "https://{gristhost}/api/docs/{docId}/tables"
52
+ TABLE_CREATE = "https://{gristhost}/api/docs/{docId}/tables"
53
+ TABLE_UPDATE = "https://{gristhost}/api/docs/{docId}/tables"
54
+
55
+ ### COLUMNS
56
+ COLUMN_ALL = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/columns"
57
+ COLUMN_CREATE = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/columns"
58
+ COLUMN_UPDATE = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/columns"
59
+ COLUMN_ADD_OR_UPDATE = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/columns"
60
+ COLUMN_DELETE = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/columns/{colId}"
61
+
62
+ ### ROWS
63
+ ROW_DELETE = "https://{gristhost}/api/docs/{docId}/tables/{tableId}/data/delete"
64
+
65
+ ### ATTACHMENTS
66
+ ATTACHMENT_ALL = "https://{gristhost}/api/docs/{docId}/attachments"
67
+ ATTACHMENT_UPDATE = "https://{gristhost}/api/docs/{docId}/attachments"
68
+ ATTACHMENT_METADATA = "https://{gristhost}/api/docs/{docId}/attachments/{attachmentId}"
69
+ ATTACHMENT_DL_CONTENT = "https://{gristhost}/api/docs/{docId}/attachments/{attachmentId}/download"
70
+
71
+ ### WEBHOOKS
72
+ WEBHOOK_ALL = "https://{gristhost}/api/docs/{docId}/webhooks"
73
+ WEBHOOK_CREATE = "https://{gristhost}/api/docs/{docId}/webhooks"
74
+ WEBHOOK_UPDATE = "https://{gristhost}/api/docs/{docId}/webhooks/{webhookId}"
75
+ WEBHOOK_DELETE = "https://{gristhost}/api/docs/{docId}/webhooks/{webhookId}"
76
+
77
+ USER_DELETE = "https://{gristhost}/api/users/{userId}"
78
+ end
79
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grist
4
+ class Response
5
+ attr_reader :data, :error, :code, :type
6
+
7
+ def initialize(data: nil, error: nil, code: nil, type: nil)
8
+ @data = data
9
+ @error = error
10
+ @type = type
11
+ @code = code&.to_i
12
+ end
13
+
14
+ def success?
15
+ error.nil? && (@code >= 200 && @code < 400)
16
+ end
17
+
18
+ def error?
19
+ !error.nil? || !(@code >= 200 && @code < 400)
20
+ end
21
+
22
+ def not_found?
23
+ @code == 404
24
+ end
25
+
26
+ def print_error
27
+ err = "#{@type}: #{@error}"
28
+ err += " (code: #{@code})" if @code
29
+ err += "\n#{@type.help}" if @type.respond_to?(:help) && !@type.help.nil?
30
+ err
31
+ end
32
+
33
+ def log_error
34
+ return unless error?
35
+
36
+ Grist.logger.error("Grist API Error: #{@type} (code: #{@code})- #{@error}")
37
+ end
38
+ end
39
+ end
data/lib/grist/rest.rb ADDED
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grist
4
+ module Rest
5
+ def request(method, endpoint, params = {})
6
+ uri = URI("#{::Grist.base_api_url}#{endpoint}")
7
+ uri.query = URI.encode_www_form(params) if method == :get
8
+
9
+ http = ::Net::HTTP.new(uri.host, uri.port)
10
+ http.use_ssl = !::Grist.localhost?
11
+
12
+ request = ::Net::HTTP.const_get(method.capitalize).new(uri)
13
+ request["Authorization"] = ::Grist.token_auth
14
+ request["Content-Type"] = "application/json"
15
+ request.body = params.to_json unless method == :get
16
+
17
+ response = http.request(request)
18
+
19
+ raise InvalidApiKey, "Invalid API key" if response.is_a?(Net::HTTPUnauthorized)
20
+ raise NotFound, "Resource not found at : #{request.uri}" if response.is_a?(Net::HTTPNotFound)
21
+
22
+ data = response_body(response.body)
23
+
24
+ Grist::Response.new(data: data, code: response.code)
25
+ rescue Net::OpenTimeout, Net::ReadTimeout, SocketError => e
26
+ res = Grist::Response.new(code: response&.code, error: "Grist endpoint is unreachable at #{request.uri}",
27
+ type: e.class)
28
+ res.log_error
29
+ raise NetworkError, res.print_error
30
+ rescue APIError => e
31
+ res = Grist::Response.new(code: response&.code, error: e.message, type: e.class)
32
+ res.log_error
33
+ res
34
+ rescue StandardError, Grist::NotFound => e
35
+ res = Grist::Response.new(code: response&.code, error: e.message, type: e.class)
36
+ res.log_error
37
+ res
38
+ end
39
+
40
+ def path
41
+ self.class::PATH
42
+ end
43
+
44
+ def list(params = {})
45
+ request(:get, path, params)
46
+ end
47
+
48
+ def get(id)
49
+ request(:get, "#{path}/#{id}")
50
+ end
51
+
52
+ def create(data)
53
+ grist_res = request(:post, path, data)
54
+ puts "Creating #{path} with data: #{data}"
55
+ puts puts grist_res.inspect
56
+ return unless grist_res.success?
57
+
58
+ data.each_key do |key|
59
+ instance_variable_set("@#{key}", data[key])
60
+ end
61
+
62
+ self
63
+ end
64
+
65
+ def update(data)
66
+ id = instance_variable_get("@id")
67
+ grist_res = request(:patch, "#{path}/#{id}", data)
68
+ return unless grist_res.success?
69
+
70
+ data.each_key do |key|
71
+ instance_variable_set("@#{key}", data[key])
72
+ end
73
+
74
+ self
75
+ end
76
+
77
+ def delete
78
+ id = instance_variable_get("@id")
79
+ grist_res = request(:delete, "#{path}/#{id}")
80
+ return unless grist_res.success?
81
+
82
+ instance_variable_set("@deleted", true)
83
+
84
+ self
85
+ end
86
+
87
+ private
88
+
89
+ def response_body(str)
90
+ return {} if str.nil? || str.empty?
91
+
92
+ JSON.parse(str)
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grist
4
+ module Searchable
5
+ # Finds a record based on the given parameters.
6
+ # @param params [Hash] The parameters to search for
7
+ # @return [Array] The records that match the given parameters
8
+ def self.find_by(*params)
9
+ objs = all
10
+ objs.select do |obj|
11
+ params.all? do |key, value|
12
+ obj.instance_variable_get("@#{key}") == value
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grist
4
+ module Type
5
+ # Defines a Grist Organization
6
+ class Access < Grist::Type::Base
7
+ PATH = "/access"
8
+ KEYS = %w[
9
+ id
10
+ email
11
+ name
12
+ picture
13
+ ref
14
+ access
15
+ isMember
16
+ ].freeze
17
+
18
+ attr_accessor(*KEYS)
19
+
20
+ # List all organizations
21
+ # @return [Array] Array of organizations
22
+ def self.all
23
+ grist_res = new.list
24
+ return [] unless grist_res&.data.is_a?(Array)
25
+
26
+ grist_res.data&.map { |org| Organization.new(org) }
27
+ end
28
+
29
+ # Finds an organization by ID
30
+ # @param id [Integer] The ID of the organization to find
31
+ # return [self | nil] The organization or nil if not found
32
+ def self.find(id)
33
+ grist_res = new.get(id)
34
+ return unless grist_res.success? && grist_res.data
35
+
36
+ new(grist_res.data)
37
+ end
38
+
39
+ # Updates the organization
40
+ # @param id [Integer] The ID of the organization to delete
41
+ # @param data [Hash] The data to update the organization with
42
+ # @return [self | nil] The updated organization or nil if not found
43
+ def self.update(id, data)
44
+ org = find(id)
45
+ return unless org
46
+
47
+ org.update(data)
48
+ end
49
+
50
+ # Deletes the organization
51
+ # @param id [Integer] The ID of the organization to delete
52
+ # @return [self | nil] The deleted organization or nil if not found
53
+ def self.delete(id)
54
+ org = find(id)
55
+ return unless org
56
+
57
+ org.delete
58
+ end
59
+
60
+ def self.access(id)
61
+ org = find(id)
62
+ grist_res = org.access
63
+ return unless grist_res.success? && grist_res.data
64
+
65
+ grist_res.data
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grist
4
+ module Type
5
+ class Base
6
+ include Rest
7
+ include Accessible
8
+ include Searchable
9
+
10
+ PATH = ""
11
+ KEYS = %w[].freeze
12
+ attr_accessor(*KEYS)
13
+
14
+ def initialize(params = {})
15
+ keys.each do |key|
16
+ instance_variable_set("@#{key}", params[key])
17
+ end
18
+ @deleted = params.delete(:deleted) || false
19
+ end
20
+
21
+ def keys
22
+ self.class::KEYS
23
+ end
24
+
25
+ def deleted?
26
+ !!@deleted
27
+ end
28
+
29
+ # List all items
30
+ # @return [Array] Array of items
31
+ def self.all
32
+ grist_res = new.list
33
+
34
+ return [] unless grist_res&.data.is_a?(Array)
35
+ return [] unless grist_res&.data&.any?
36
+
37
+ grist_res.data.map { |org| new(org) }
38
+ end
39
+
40
+ # Finds an item by ID
41
+ # @param id [Integer] The ID of the item to find
42
+ # return [Grist::Type::Base, nil] The item or nil if not found
43
+ def self.find(id)
44
+ grist_res = new.get(id)
45
+ return unless grist_res.success? && grist_res.data
46
+
47
+ new(grist_res.data)
48
+ end
49
+
50
+ # Updates the item
51
+ # @param id [Integer] The ID of the item to delete
52
+ # @param data [Hash] The data to update the item with
53
+ # @return [Grist::Type::Base, nil] The updated item or nil if not found
54
+ def self.update(id, data)
55
+ org = find(id)
56
+ return unless org
57
+
58
+ org.update(data)
59
+ end
60
+
61
+ # Deletes the item
62
+ # @param id [Integer] The ID of the item to delete
63
+ # @return [Grist::Type::Base, nil] The deleted item or nil if not found
64
+ def self.delete(id)
65
+ org = find(id)
66
+ return unless org
67
+
68
+ org.delete
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grist
4
+ module Type
5
+ # Defines a Grist Workspace
6
+ class Column
7
+ include Rest
8
+
9
+ PATH = "/docs"
10
+ KEYS = %w[
11
+ id
12
+ fields
13
+ ].freeze
14
+
15
+ attr_accessor(*KEYS)
16
+
17
+ def initialize(params = {})
18
+ @doc_id = params[:doc_id]
19
+ KEYS.each do |key|
20
+ instance_variable_set("@#{key}", params[key])
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end