sheets_v4 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e8b306cf08149067ba4f5506c54c88df4e2af706f064b3b2b7cc7f5919991f4
4
- data.tar.gz: 438a64d88598542b9f9ed56552077836089e04b411aa8a4ceabf5279b131a393
3
+ metadata.gz: 27e014c65904a88e3fb4df001a8b28c64c307363b3cd658da252a951c55da992
4
+ data.tar.gz: c6900f0d163abdb621a49080295ca7e59f82b89bae69d5e5729aa74aac765a1b
5
5
  SHA512:
6
- metadata.gz: 3728b1539d987a5aa7dfbbb45d0a9637d01c39d5fe3d8a3e19cd7206b9fab4b9ce1458d1f6e534e6ddb79d93d2792c93f940f3a800f2eb657647dd4dfdebceb9
7
- data.tar.gz: fe7d8f59b7663f76804d18e13ece431bdce418252efe51a2e50d28a5d3e5fe1c979b367287155032e82571e09c593bd9be2b40cc461901a4bf5bec728cfcc8e2
6
+ metadata.gz: e60614708c5f348d05388a1bfe7b51603a92797e852aa20445d37451a493655aac69ea86fd901d500a9898a289f469d9a3780fdbe2f2756cfb80a65110641455
7
+ data.tar.gz: 71ea62ff3e93faf9d9ece533ccd98f5491dea2f04d00d01c01020dd501a251a3b0b61544e0e57e85643fc0afedbfe97e92250d71b5968c63650822f0e3338433
data/.markdownlint.yml ADDED
@@ -0,0 +1,25 @@
1
+ default: true
2
+
3
+ # Unordered list indentation
4
+ MD007: { indent: 2 }
5
+
6
+ # Line length
7
+ MD013: { line_length: 90, tables: false, code_blocks: false }
8
+
9
+ # Heading duplication is allowed for non-sibling headings
10
+ MD024: { siblings_only: true }
11
+
12
+ # Do not allow the specified trailig punctuation in a header
13
+ MD026: { punctuation: '.,;:' }
14
+
15
+ # Order list items must have a prefix that increases in numerical order
16
+ MD029: { style: 'ordered' }
17
+
18
+ # Lists do not need to be surrounded by blank lines
19
+ MD032: false
20
+
21
+ # Allow raw HTML in Markdown
22
+ MD033: false
23
+
24
+ # Allow emphasis to be used instead of a heading
25
+ MD036: false
data/.rubocop.yml CHANGED
@@ -23,6 +23,9 @@ Metrics/BlockLength:
23
23
  - "spec/**/*_spec.rb"
24
24
  - "*.gemspec"
25
25
 
26
+ Metrics/ModuleLength:
27
+ CountAsOne: ['hash']
28
+
26
29
  # When writing minitest tests, it is very hard to limit test class length:
27
30
  Metrics/ClassLength:
28
31
  Exclude:
data/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ Changes for each release are listed in this file.
4
4
 
5
5
  This project adheres to [Semantic Versioning](https://semver.org/) for its releases.
6
6
 
7
+ ## v0.3.0 (2023-09-28)
8
+
9
+ [Full Changelog](https://github.com/main-branch/sheets_v4/compare/v0.2.0..v0.3.0)
10
+
11
+ Changes since v0.2.0:
12
+
13
+ * 0fb4579 Add predefined color objects (#8)
14
+
15
+ ## v0.2.0 (2023-09-26)
16
+
17
+ [Full Changelog](https://github.com/main-branch/sheets_v4/compare/v0.1.1..v0.2.0)
18
+
19
+ Changes since v0.1.1:
20
+
21
+ * 489ff50 Add SheetsV4.validate_api_object (#6)
22
+ * b44eba4 List all examples that should be created (#5)
23
+ * 2edd688 Add links to Google Sheets documentation to the README.md (#4)
24
+
7
25
  ## v0.1.1 (2023-09-22)
8
26
 
9
27
  [Full Changelog](https://github.com/main-branch/sheets_v4/compare/v0.1.0..v0.1.1)
data/README.md CHANGED
@@ -9,12 +9,33 @@
9
9
 
10
10
  Unofficial helpers for the Google Sheets V4 API
11
11
 
12
- - [SheetsV4](#sheetsv4)
13
- - [Installation](#installation)
14
- - [Usage](#usage)
15
- - [Development](#development)
16
- - [Contributing](#contributing)
17
- - [License](#license)
12
+ * [Important Links for Programming Google Sheets](#important-links-for-programming-google-sheets)
13
+ * [General API Documentation](#general-api-documentation)
14
+ * [Ruby Implementation of the Sheets API](#ruby-implementation-of-the-sheets-api)
15
+ * [Other Links](#other-links)
16
+ * [Installation](#installation)
17
+ * [Usage](#usage)
18
+ * [Development](#development)
19
+ * [Creating a Google API Service Account](#creating-a-google-api-service-account)
20
+ * [Contributing](#contributing)
21
+ * [License](#license)
22
+
23
+ ## Important Links for Programming Google Sheets
24
+
25
+ ### General API Documentation
26
+
27
+ * [Google Sheets API Overview](https://developers.google.com/sheets/api)
28
+ * [Google Sheets API Reference](https://developers.google.com/sheets/api/reference/rest)
29
+ * [Batch Update Requests](https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request)
30
+
31
+ ### Ruby Implementation of the Sheets API
32
+
33
+ * [SheetsService Class](https://github.com/googleapis/google-api-ruby-client/blob/main/generated/google-apis-sheets_v4/lib/google/apis/sheets_v4/service.rb)
34
+ * [All Other Sheets Classes](https://github.com/googleapis/google-api-ruby-client/blob/main/generated/google-apis-sheets_v4/lib/google/apis/sheets_v4/classes.rb)
35
+
36
+ ### Other Links
37
+
38
+ * [Apps Script for Sheets](https://developers.google.com/apps-script/guides/sheets)
18
39
 
19
40
  ## Installation
20
41
 
@@ -46,6 +67,9 @@ release a new version, update the version number in `version.rb`, and then run
46
67
  commits and the created tag, and push the `.gem` file to
47
68
  [rubygems.org](https://rubygems.org).
48
69
 
70
+ ## Creating a Google API Service Account
71
+
72
+
49
73
  ## Contributing
50
74
 
51
75
  Bug reports and pull requests are welcome on [the main-branch/sheets_v4 GitHub project](https://github.com/main-branch/sheets_v4).
@@ -53,4 +77,4 @@ Bug reports and pull requests are welcome on [the main-branch/sheets_v4 GitHub p
53
77
  ## License
54
78
 
55
79
  The gem is available as open source under the terms of the
56
- [MIT License](https://opensource.org/licenses/MIT).
80
+ [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ desc 'Run the same tasks that the CI build will run'
4
4
  if RUBY_PLATFORM == 'java'
5
5
  task default: %w[spec rubocop bundle:audit build]
6
6
  else
7
- task default: %w[spec rubocop yard yard:audit yard:coverage bundle:audit build]
7
+ task default: %w[spec rubocop yard bundle:audit build]
8
8
  end
9
9
 
10
10
  # Bundler Audit
@@ -58,28 +58,41 @@ end
58
58
  CLEAN << 'rubocop-report.json'
59
59
 
60
60
  unless RUBY_PLATFORM == 'java'
61
- # YARD
61
+ # yard:build
62
62
 
63
63
  require 'yard'
64
- YARD::Rake::YardocTask.new do |t|
65
- t.files = %w[lib/**/*.rb examples/**/*]
64
+
65
+ YARD::Rake::YardocTask.new('yard:build') do |t|
66
+ t.files = %w[lib/**/*.rb]
67
+ t.stats_options = ['--list-undoc']
66
68
  end
67
69
 
68
70
  CLEAN << '.yardoc'
69
71
  CLEAN << 'doc'
70
72
 
71
- # Yardstick
73
+ # yard:audit
72
74
 
73
75
  desc 'Run yardstick to show missing YARD doc elements'
74
76
  task :'yard:audit' do
75
77
  sh "yardstick 'lib/**/*.rb'"
76
78
  end
77
79
 
78
- # Yardstick coverage
80
+ # yard:coverage
79
81
 
80
82
  require 'yardstick/rake/verify'
81
83
 
82
84
  Yardstick::Rake::Verify.new(:'yard:coverage') do |verify|
83
85
  verify.threshold = 100
86
+ verify.require_exact_threshold = false
87
+ end
88
+
89
+ task yard: %i[yard:build yard:audit yard:coverage]
90
+
91
+ # github-pages:publish
92
+
93
+ require 'github_pages_rake_tasks'
94
+ GithubPagesRakeTasks::PublishTask.new do |task|
95
+ # task.doc_dir = 'documentation'
96
+ task.verbose = true
84
97
  end
85
98
  end
@@ -0,0 +1,47 @@
1
+ # Google Sheets Examples
2
+
3
+ * [ ] Creating a Google API service account [1](https://www.youtube.com/watch?v=sAgWCbGMzTo&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=1)
4
+ [2](https://www.youtube.com/watch?v=sVURhxyc6jE&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=43)
5
+ * [ ] Create a SheetsService instance
6
+ * [ ] Creating Google Sheets files [1](https://www.youtube.com/watch?v=JRUxeQ6ZCy0&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=2)
7
+ * [ ] Writing data to a sheet [1](https://www.youtube.com/watch?v=YF7Ad-7pvks&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=3)
8
+ * [ ] Reading data from a sheet [1](https://www.youtube.com/watch?v=gkglr8GID5E&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=4)
9
+ * Reading data
10
+ * Reading formulas
11
+ * [ ] Data formatting basics [1](https://www.youtube.com/watch?v=R4EN3iPRris&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=5)
12
+ * [ ] Creating charts [1](https://www.youtube.com/watch?v=xt3p5I8mNWE&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=6)
13
+ * [ ] Data validation [1](https://www.youtube.com/watch?v=n_Z2565gu6Y&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=7)
14
+ * [ ] Cut, copy, and paste [1](https://www.youtube.com/watch?v=r8GWH2E_ehw&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=8)
15
+ * [ ] Duplicate sheets [1](https://www.youtube.com/watch?v=BgQoPcoOiGY&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=9)
16
+ * [ ] List sheets in a spreadsheet [1](https://www.youtube.com/watch?v=BgQoPcoOiGY&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=9)
17
+ * [ ] Set column width and row height [1](https://www.youtube.com/watch?v=H3uMEaPqTVE&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=11)
18
+ * [ ] Append rows and columns [1](https://www.youtube.com/watch?v=txfiwEjb7sk&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=12)
19
+ * [ ] Delete rows and columns [1](https://www.youtube.com/watch?v=w1jrCxWx7Tc&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=13)
20
+ * [ ] Insert rows and columns [1](https://www.youtube.com/watch?v=FL7WSsO5EVs&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=14)
21
+ * [ ] Move rows and columns [1](https://www.youtube.com/watch?v=YHk3305dkOc&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=15)
22
+ * [ ] Clear data [1](https://www.youtube.com/watch?v=mvbnhfdDrro&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=16)
23
+ * [ ] Add and delete sheets [1](https://www.youtube.com/watch?v=X9PVQQVoJFc&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=17)
24
+ * [ ] Copy sheet from one spreadsheet to another [1](https://www.youtube.com/watch?v=aIEM7Ts4n-c&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=18)
25
+ * [ ] Add a new sheet to an existing spreadsheet
26
+ * [ ] Export a sheet to a CSV file [1](https://www.youtube.com/watch?v=Dz22fsWsLhI&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=25)
27
+ * [ ] Sort sheets [1](https://www.youtube.com/watch?v=qbBZX7uBM1M&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=27)
28
+ * [ ] Add calculated fields into a pivot table [1](https://www.youtube.com/watch?v=VR8zOz5ATLU&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=32)
29
+ * [ ] Named ranges [1](https://www.youtube.com/watch?v=LTPdfXS_LHA&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=42)
30
+ * [ ] Create a pivot table [1](https://www.youtube.com/watch?v=preFnuL7ua0&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=28)
31
+ * [ ] Calculated pivot fields [1](https://www.youtube.com/watch?v=QLssI4uvjk4&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=33)
32
+ * [ ] Delete a pivot table
33
+ * [ ] Add pivot fields [1](https://www.youtube.com/watch?v=VR8zOz5ATLU&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=32)
34
+ * [ ] Add pivot filters [1](https://www.youtube.com/watch?v=EKikw-eIcbY&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=29)
35
+ * [ ] Collapse/expand pivot table groups [1](https://www.youtube.com/watch?v=-S9bs5-ZJ5E&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=31)
36
+ * [ ] Extract pivot table metadata [1](https://www.youtube.com/watch?v=H1SGdqbaL4w&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=30)
37
+ * [ ] Filter views [1](https://www.youtube.com/watch?v=GyRxsSlx0GU&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=34)
38
+ * [ ] Locate the last row in a column [1](https://www.youtube.com/watch?v=NWWHleJll28&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=35)
39
+ * [ ] Autofill [1](https://www.youtube.com/watch?v=guHGNmODdpM&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=36)
40
+ * [ ] Rename a sheet [1](https://www.youtube.com/watch?v=iuiDUJ4NrQI&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=37)
41
+ * [ ] Find and replace [1](https://www.youtube.com/watch?v=YaFR0bu5CrY&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=39)
42
+ * [ ] Add and delete sheets [1](https://www.youtube.com/watch?v=gMD4v8F8vlc&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=38)
43
+ * [ ] Sum across sheets [1](https://www.youtube.com/watch?v=7QNk-MXkPC4&list=PL3JVwFmb_BnSee8RFaRPZ3nykuMRlaQp1&index=44)
44
+ * [ ] Freeze rows / columns
45
+ * [ ] Protected ranges
46
+ * [ ] Resize a sheet
47
+ * [ ] Retrying on error
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json_schemer'
4
+
5
+ module SheetsV4
6
+ # Predefined color objects
7
+ # @api public
8
+ class Color
9
+ class << self
10
+ # Return a color object for the given name from SheetsV4::COLORS or call super
11
+ #
12
+ # @param method_name [Symbol] the name of the color
13
+ # @param arguments [Array] ignored
14
+ # @param block [Proc] ignored
15
+ # @return [Hash] the color object
16
+ # @api private
17
+ def method_missing(method_name, *arguments, &)
18
+ SheetsV4::COLORS[method_name.to_sym] || super
19
+ end
20
+
21
+ # Return true if the given method name is a color name or call super
22
+ #
23
+ # @param method_name [Symbol] the name of the color
24
+ # @param include_private [Boolean] ignored
25
+ # @return [Boolean] true if the method name is a color name
26
+ # @api private
27
+ def respond_to_missing?(method_name, include_private = false)
28
+ SheetsV4::COLORS.key?(method_name.to_sym) || super
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json_schemer'
4
+
5
+ module SheetsV4
6
+ # Validate objects against a Google Sheets API request object schema
7
+ #
8
+ # @api public
9
+ #
10
+ class ValidateApiObject
11
+ # Create a new validator
12
+ #
13
+ # By default, a nil logger is used. This means that no messages are logged.
14
+ #
15
+ # @example
16
+ # logger = Logger.new(STDOUT, :level => Logger::INFO)
17
+ # validator = SheetsV4::ValidateApiObject.new(logger)
18
+ #
19
+ # @param logger [Logger] the logger to use
20
+ #
21
+ def initialize(logger = Logger.new(nil))
22
+ @logger = logger
23
+ end
24
+
25
+ # The logger to use internally
26
+ #
27
+ # Validation errors are logged at the error level. Other messages are logged
28
+ # at the debug level.
29
+ #
30
+ # @example
31
+ # logger = Logger.new(STDOUT, :level => Logger::INFO)
32
+ # validator = SheetsV4::ValidateApiObject.new(logger)
33
+ # validator.logger == logger # => true
34
+ # validator.logger.debug { "Debug message" }
35
+ #
36
+ # @return [Logger]
37
+ #
38
+ attr_reader :logger
39
+
40
+ # Validate the object using the JSON schema named schema_name
41
+ #
42
+ # @example
43
+ # schema_name = 'BatchUpdateSpreadsheetRequest'
44
+ # object = { 'requests' => [] }
45
+ # validator = SheetsV4::ValidateApiObject.new
46
+ # validator.call(schema_name, object)
47
+ #
48
+ # @param schema_name [String] the name of the schema to validate against
49
+ # @param object [Object] the object to validate
50
+ #
51
+ # @raise [RuntimeError] if the object does not conform to the schema
52
+ #
53
+ # @return [void]
54
+ #
55
+ def call(schema_name, object)
56
+ logger.debug { "Validating #{object} against #{schema_name}" }
57
+
58
+ schema = { '$ref' => schema_name }
59
+ schemer = JSONSchemer.schema(schema, ref_resolver:)
60
+ errors = schemer.validate(object)
61
+ raise_error!(schema_name, object, errors) if errors.any?
62
+
63
+ logger.debug { "Object #{object} conforms to #{schema_name}" }
64
+ end
65
+
66
+ private
67
+
68
+ # The resolver to use to resolve JSON schema references
69
+ # @return [SchemaRefResolver]
70
+ # @api private
71
+ def ref_resolver = @ref_resolver ||= SchemaRefResolver.new(logger)
72
+
73
+ # Raise an error when the object does not conform to the schema
74
+ # @return [void]
75
+ # @raise [RuntimeError]
76
+ # @api private
77
+ def raise_error!(schema_name, object, errors)
78
+ error = errors.first['error']
79
+ error_message = "Object #{object} does not conform to #{schema_name}: #{error}"
80
+ logger.error(error_message)
81
+ raise error_message
82
+ end
83
+ end
84
+
85
+ # Resolve JSON schema references to Google Sheets API schemas
86
+ #
87
+ # Uses the Google Discovery API to get the schemas. This is an implementation
88
+ # detail used to interact with JSONSchemer.
89
+ #
90
+ # @api private
91
+ #
92
+ class SchemaRefResolver
93
+ # Create a new schema resolver
94
+ #
95
+ # @param logger [Logger] the logger to use
96
+ #
97
+ # @api private
98
+ #
99
+ def initialize(logger)
100
+ @logger = logger
101
+ end
102
+
103
+ # The logger to use internally
104
+ #
105
+ # Currently, only info messages are logged.
106
+ #
107
+ # @return [Logger]
108
+ #
109
+ # @api private
110
+ #
111
+ attr_reader :logger
112
+
113
+ # Resolve a JSON schema reference
114
+ #
115
+ # @param ref [String] the reference to resolve usually in the form "#/definitions/schema_name"
116
+ #
117
+ # @return [Hash] the schema object as a hash
118
+ #
119
+ # @api private
120
+ #
121
+ def call(ref)
122
+ schema_name = ref.path[1..]
123
+ logger.debug { "Reading schema #{schema_name}" }
124
+ schema_object = SheetsV4.api_object_schemas[schema_name]
125
+ raise "Schema for #{ref} not found" unless schema_object
126
+
127
+ schema_object.to_h.tap do |schema|
128
+ schema['unevaluatedProperties'] = false
129
+ end
130
+ end
131
+ end
132
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SheetsV4
4
- VERSION = '0.1.1'
4
+ # The version of this gem
5
+ VERSION = '0.3.0'
5
6
  end
data/lib/sheets_v4.rb CHANGED
@@ -1,8 +1,242 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'sheets_v4/version'
4
+ require_relative 'sheets_v4/color'
5
+ require_relative 'sheets_v4/validate_api_object'
4
6
 
7
+ require 'json'
8
+ require 'logger'
9
+ require 'net/http'
10
+
11
+ # Unofficial helpers for the Google Sheets V4 API
12
+ #
13
+ # @api public
14
+ #
5
15
  module SheetsV4
6
- class Error < StandardError; end
7
- # Your code goes here...
16
+ # Validate the object using the named JSON schema
17
+ #
18
+ # The JSON schemas are loaded from the Google Disocvery API. The schemas names are
19
+ # returned by `SheetsV4.api_object_schemas.keys`.
20
+ #
21
+ # @example
22
+ # schema_name = 'BatchUpdateSpreadsheetRequest'
23
+ # object = { 'requests' => [] }
24
+ # SheetsV4.validate_api_object(schema_name:, object:)
25
+ #
26
+ # @param schema_name [String] the name of the schema to validate against
27
+ # @param object [Object] the object to validate
28
+ # @param logger [Logger] the logger to use for logging error, info, and debug message
29
+ #
30
+ # @raise [RuntimeError] if the object does not conform to the schema
31
+ #
32
+ # @return [void]
33
+ #
34
+ def self.validate_api_object(schema_name:, object:, logger: Logger.new(nil))
35
+ ValidateApiObject.new(logger).call(schema_name, object)
36
+ end
37
+
38
+ # A hash of schemas keyed by the schema name loaded from the Google Discovery API
39
+ #
40
+ # @example
41
+ # SheetsV4.api_object_schemas #=> { 'PersonSchema' => { 'type' => 'object', ... } ... }
42
+ #
43
+ # @return [Hash<String, Object>] a hash of schemas keyed by schema name
44
+ #
45
+ def self.api_object_schemas
46
+ schema_load_semaphore.synchronize { @api_object_schemas ||= load_api_object_schemas }
47
+ end
48
+
49
+ # Validate
50
+ # A mutex used to synchronize access to the schemas so they are only loaded
51
+ # once.
52
+ #
53
+ @schema_load_semaphore = Thread::Mutex.new
54
+
55
+ # A mutex used to synchronize access to the schemas so they are only loaded once
56
+ #
57
+ # @return [Thread::Mutex]
58
+ #
59
+ # @api private
60
+ #
61
+ def self.schema_load_semaphore = @schema_load_semaphore
62
+
63
+ # Load the schemas from the Google Discovery API
64
+ #
65
+ # @return [Hash<String, Object>] a hash of schemas keyed by schema name
66
+ #
67
+ # @api private
68
+ #
69
+ def self.load_api_object_schemas
70
+ source = 'https://sheets.googleapis.com/$discovery/rest?version=v4'
71
+ resp = Net::HTTP.get_response(URI.parse(source))
72
+ data = resp.body
73
+ JSON.parse(data)['schemas'].tap do |schemas|
74
+ schemas.each { |_name, schema| schema['unevaluatedProperties'] = false }
75
+ end
76
+ end
77
+
78
+ # Return a color object for the given name from SheetsV4::COLORS
79
+ #
80
+ # @example
81
+ # SheetsV4::Color.color(:red) #=> { "red": 1.0, "green": 0.0, "blue": 0.0 }
82
+ #
83
+ # @param name [Symbol] the name of the color
84
+ # @return [Hash] the color object
85
+ # @api public
86
+ def self.color(name)
87
+ SheetsV4::COLORS[name.to_sym]
88
+ end
89
+
90
+ # Colors to use in the Google Sheets API
91
+ COLORS = {
92
+ # Standard Google Sheets colors
93
+
94
+ black: { red: 0.000000000, green: 0.000000000, blue: 0.000000000 },
95
+ dark_gray4: { red: 0.262745098, green: 0.262745098, blue: 0.262745098 },
96
+ dark_gray3: { red: 0.400000000, green: 0.400000000, blue: 0.400000000 },
97
+ dark_gray2: { red: 0.600000000, green: 0.600000000, blue: 0.600000000 },
98
+ dark_gray1: { red: 0.717647059, green: 0.717647059, blue: 0.717647059 },
99
+ gray: { red: 0.800000000, green: 0.800000000, blue: 0.800000000 },
100
+ light_gray1: { red: 0.850980392, green: 0.850980392, blue: 0.850980392 },
101
+ light_gray2: { red: 0.937254902, green: 0.937254902, blue: 0.937254902 },
102
+ light_gray3: { red: 0.952941176, green: 0.952941176, blue: 0.952941176 },
103
+ white: { red: 1.000000000, green: 1.000000000, blue: 1.000000000 },
104
+ red_berry: { red: 0.596078431, green: 0.000000000, blue: 0.000000000 },
105
+ red: { red: 1.000000000, green: 0.000000000, blue: 0.000000000 },
106
+ orange: { red: 1.000000000, green: 0.600000000, blue: 0.000000000 },
107
+ yellow: { red: 1.000000000, green: 1.000000000, blue: 0.000000000 },
108
+ green: { red: 0.000000000, green: 1.000000000, blue: 0.000000000 },
109
+ cyan: { red: 0.000000000, green: 1.000000000, blue: 1.000000000 },
110
+ cornflower_blue: { red: 0.290196078, green: 0.525490196, blue: 0.909803922 },
111
+ blue: { red: 0.000000000, green: 0.000000000, blue: 1.000000000 },
112
+ purple: { red: 0.600000000, green: 0.000000000, blue: 1.000000000 },
113
+ magenta: { red: 1.000000000, green: 0.000000000, blue: 1.000000000 },
114
+ light_red_berry3: { red: 0.901960784, green: 0.721568627, blue: 0.686274510 },
115
+ light_red3: { red: 0.956862745, green: 0.800000000, blue: 0.800000000 },
116
+ light_orange3: { red: 0.988235294, green: 0.898039216, blue: 0.803921569 },
117
+ light_yellow3: { red: 1.000000000, green: 0.949019608, blue: 0.800000000 },
118
+ light_green3: { red: 0.850980392, green: 0.917647059, blue: 0.827450980 },
119
+ light_cyan3: { red: 0.815686275, green: 0.878431373, blue: 0.890196078 },
120
+ light_cornflower_blue3: { red: 0.788235294, green: 0.854901961, blue: 0.972549020 },
121
+ light_blue3: { red: 0.811764706, green: 0.886274510, blue: 0.952941176 },
122
+ light_purple3: { red: 0.850980392, green: 0.823529412, blue: 0.913725490 },
123
+ light_magenta3: { red: 0.917647059, green: 0.819607843, blue: 0.862745098 },
124
+ light_red_berry2: { red: 0.866666667, green: 0.494117647, blue: 0.419607843 },
125
+ light_red2: { red: 0.917647059, green: 0.600000000, blue: 0.600000000 },
126
+ light_orange2: { red: 0.976470588, green: 0.796078431, blue: 0.611764706 },
127
+ light_yellow2: { red: 1.000000000, green: 0.898039216, blue: 0.600000000 },
128
+ light_green2: { red: 0.713725490, green: 0.843137255, blue: 0.658823529 },
129
+ light_cyan2: { red: 0.635294118, green: 0.768627451, blue: 0.788235294 },
130
+ light_cornflower_blue2: { red: 0.643137255, green: 0.760784314, blue: 0.956862745 },
131
+ light_blue2: { red: 0.623529412, green: 0.772549020, blue: 0.909803922 },
132
+ light_purple2: { red: 0.705882353, green: 0.654901961, blue: 0.839215686 },
133
+ light_magenta2: { red: 0.835294118, green: 0.650980392, blue: 0.741176471 },
134
+ light_red_berry1: { red: 0.800000000, green: 0.254901961, blue: 0.145098039 },
135
+ light_red1: { red: 0.878431373, green: 0.400000000, blue: 0.400000000 },
136
+ light_orange1: { red: 0.964705882, green: 0.698039216, blue: 0.419607843 },
137
+ light_yellow1: { red: 1.000000000, green: 0.850980392, blue: 0.400000000 },
138
+ light_green1: { red: 0.576470588, green: 0.768627451, blue: 0.490196078 },
139
+ light_cyan1: { red: 0.462745098, green: 0.647058824, blue: 0.686274510 },
140
+ light_cornflower_blue1: { red: 0.427450980, green: 0.619607843, blue: 0.921568627 },
141
+ light_blue1: { red: 0.435294118, green: 0.658823529, blue: 0.862745098 },
142
+ light_purple1: { red: 0.556862745, green: 0.486274510, blue: 0.764705882 },
143
+ light_magenta1: { red: 0.760784314, green: 0.482352941, blue: 0.627450980 },
144
+ dark_red_berry1: { red: 0.650980392, green: 0.109803922, blue: 0.000000000 },
145
+ dark_red1: { red: 0.800000000, green: 0.000000000, blue: 0.000000000 },
146
+ dark_orange1: { red: 0.901960784, green: 0.568627451, blue: 0.219607843 },
147
+ dark_yellow1: { red: 0.945098039, green: 0.760784314, blue: 0.196078431 },
148
+ dark_green1: { red: 0.415686275, green: 0.658823529, blue: 0.309803922 },
149
+ dark_cyan1: { red: 0.270588235, green: 0.505882353, blue: 0.556862745 },
150
+ dark_cornflower_blue1: { red: 0.235294118, green: 0.470588235, blue: 0.847058824 },
151
+ dark_blue1: { red: 0.239215686, green: 0.521568627, blue: 0.776470588 },
152
+ dark_purple1: { red: 0.403921569, green: 0.305882353, blue: 0.654901961 },
153
+ dark_magenta1: { red: 0.650980392, green: 0.301960784, blue: 0.474509804 },
154
+ dark_red_berry2: { red: 0.521568627, green: 0.125490196, blue: 0.047058824 },
155
+ dark_red2: { red: 0.600000000, green: 0.000000000, blue: 0.000000000 },
156
+ dark_orange2: { red: 0.705882353, green: 0.372549020, blue: 0.023529412 },
157
+ dark_yellow2: { red: 0.749019608, green: 0.564705882, blue: 0.000000000 },
158
+ dark_green2: { red: 0.219607843, green: 0.462745098, blue: 0.113725490 },
159
+ dark_cyan2: { red: 0.074509804, green: 0.309803922, blue: 0.360784314 },
160
+ dark_cornflower_blue2: { red: 0.066666667, green: 0.333333333, blue: 0.800000000 },
161
+ dark_blue2: { red: 0.043137255, green: 0.325490196, blue: 0.580392157 },
162
+ dark_purple2: { red: 0.207843137, green: 0.109803922, blue: 0.458823529 },
163
+ dark_magenta2: { red: 0.454901961, green: 0.105882353, blue: 0.278431373 },
164
+ dark_red_berry3: { red: 0.356862745, green: 0.058823529, blue: 0.000000000 },
165
+ dark_red3: { red: 0.400000000, green: 0.000000000, blue: 0.000000000 },
166
+ dark_orange3: { red: 0.470588235, green: 0.247058824, blue: 0.015686275 },
167
+ dark_yellow3: { red: 0.498039216, green: 0.376470588, blue: 0.000000000 },
168
+ dark_green3: { red: 0.152941176, green: 0.305882353, blue: 0.074509804 },
169
+ darn_cyan3: { red: 0.047058824, green: 0.203921569, blue: 0.239215686 },
170
+ dark_cornflower_blue3: { red: 0.109803922, green: 0.270588235, blue: 0.529411765 },
171
+ dark_blue3: { red: 0.027450980, green: 0.215686275, blue: 0.388235294 },
172
+ dark_purple3: { red: 0.125490196, green: 0.070588235, blue: 0.301960784 },
173
+ dark_magenta3: { red: 0.298039216, green: 0.066666667, blue: 0.188235294 },
174
+
175
+ # Yahoo brand colors
176
+
177
+ grape_jelly: { red: 0.376470588, green: 0.003921569, blue: 0.823529412 },
178
+ hulk_pants: { red: 0.494117647, green: 0.121568627, blue: 1.000000000 },
179
+ malbec: { red: 0.223529412, green: 0.000000000, blue: 0.490196078 },
180
+ tumeric: { red: 1.000000000, green: 0.654901961, blue: 0.000000000 },
181
+ mulah: { red: 0.101960784, green: 0.772549020, blue: 0.403921569 },
182
+ dory: { red: 0.058823529, green: 0.411764706, blue: 1.000000000 },
183
+ malibu: { red: 1.000000000, green: 0.000000000, blue: 0.501960784 },
184
+ sea_foam: { red: 0.066666667, green: 0.827450980, blue: 0.803921569 },
185
+ tumeric_tint: { red: 0.980392157, green: 0.866666667, blue: 0.694117647 },
186
+ mulah_tint: { red: 0.733333333, green: 0.901960784, blue: 0.776470588 },
187
+ dory_tint: { red: 0.662745098, green: 0.772549020, blue: 0.984313725 },
188
+ malibu_tint: { red: 0.968627451, green: 0.682352941, blue: 0.800000000 },
189
+ sea_foam_tint: { red: 0.749019608, green: 0.925490196, blue: 0.921568627 },
190
+
191
+ # Yahoo health colors
192
+
193
+ health_green: { red: 0.000000000, green: 0.690196078, blue: 0.313725490 },
194
+ health_yellow: { red: 1.000000000, green: 0.654901961, blue: 0.000000000 },
195
+ health_red: { red: 1.000000000, green: 0.000000000, blue: 0.000000000 },
196
+
197
+ # Yahoo Fuji design color palette
198
+
199
+ fuji_color_watermelon: { red: 1.000000000, green: 0.321568627, blue: 0.341176471 },
200
+ fuji_color_solo_cup: { red: 0.921568627, green: 0.058823529, blue: 0.160784314 },
201
+ fuji_color_malibu: { red: 1.000000000, green: 0.000000000, blue: 0.501960784 },
202
+ fuji_color_barney: { red: 0.800000000, green: 0.000000000, blue: 0.549019608 },
203
+ fuji_color_mimosa: { red: 1.000000000, green: 0.827450980, blue: 0.200000000 },
204
+ fuji_color_turmeric: { red: 1.000000000, green: 0.654901961, blue: 0.000000000 },
205
+ fuji_color_cheetos: { red: 0.992156863, green: 0.380392157, blue: 0.000000000 },
206
+ fuji_color_carrot_juice: { red: 1.000000000, green: 0.321568627, blue: 0.050980392 },
207
+ fuji_color_mulah: { red: 0.101960784, green: 0.772549020, blue: 0.403921569 },
208
+ fuji_color_bonsai: { red: 0.000000000, green: 0.529411765, blue: 0.317647059 },
209
+ fuji_color_spirulina: { red: 0.000000000, green: 0.627450980, blue: 0.627450980 },
210
+ fuji_color_sea_foam: { red: 0.066666667, green: 0.827450980, blue: 0.803921569 },
211
+ fuji_color_peeps: { red: 0.490196078, green: 0.796078431, blue: 1.000000000 },
212
+ fuji_color_sky: { red: 0.070588235, green: 0.662745098, blue: 1.000000000 },
213
+ fuji_color_dory: { red: 0.058823529, green: 0.411764706, blue: 1.000000000 },
214
+ fuji_color_scooter: { red: 0.000000000, green: 0.388235294, blue: 0.921568627 },
215
+ fuji_color_cobalt: { red: 0.000000000, green: 0.227450980, blue: 0.737254902 },
216
+ fuji_color_denim: { red: 0.101960784, green: 0.050980392, blue: 0.670588235 },
217
+ fuji_color_blurple: { red: 0.364705882, green: 0.368627451, blue: 1.000000000 },
218
+ fuji_color_hendrix: { red: 0.972549020, green: 0.956862745, blue: 1.000000000 },
219
+ fuji_color_thanos: { red: 0.564705882, green: 0.486274510, blue: 1.000000000 },
220
+ fuji_color_starfish: { red: 0.466666667, green: 0.349019608, blue: 1.000000000 },
221
+ fuji_color_hulk_pants: { red: 0.494117647, green: 0.121568627, blue: 1.000000000 },
222
+ fuji_color_grape_jelly: { red: 0.376470588, green: 0.003921569, blue: 0.823529412 },
223
+ fuji_color_mulberry: { red: 0.313725490, green: 0.082352941, blue: 0.690196078 },
224
+ fuji_color_malbec: { red: 0.223529412, green: 0.000000000, blue: 0.490196078 },
225
+ fuji_grayscale_black: { red: 0.000000000, green: 0.000000000, blue: 0.000000000 },
226
+ fuji_grayscale_midnight: { red: 0.062745098, green: 0.082352941, blue: 0.094117647 },
227
+ fuji_grayscale_inkwell: { red: 0.113725490, green: 0.133333333, blue: 0.156862745 },
228
+ fuji_grayscale_batcave: { red: 0.137254902, green: 0.164705882, blue: 0.192156863 },
229
+ fuji_grayscale_ramones: { red: 0.172549020, green: 0.211764706, blue: 0.247058824 },
230
+ fuji_grayscale_charcoal: { red: 0.274509804, green: 0.305882353, blue: 0.337254902 },
231
+ fuji_grayscale_battleship: { red: 0.356862745, green: 0.388235294, blue: 0.415686275 },
232
+ fuji_grayscale_dolphin: { red: 0.431372549, green: 0.466666667, blue: 0.501960784 },
233
+ fuji_grayscale_shark: { red: 0.509803922, green: 0.541176471, blue: 0.576470588 },
234
+ fuji_grayscale_gandalf: { red: 0.592156863, green: 0.619607843, blue: 0.658823529 },
235
+ fuji_grayscale_bob: { red: 0.690196078, green: 0.725490196, blue: 0.756862745 },
236
+ fuji_grayscale_pebble: { red: 0.780392157, green: 0.803921569, blue: 0.823529412 },
237
+ fuji_grayscale_dirty_seagull: { red: 0.878431373, green: 0.894117647, blue: 0.913725490 },
238
+ fuji_grayscale_grey_hair: { red: 0.941176471, green: 0.952941176, blue: 0.960784314 },
239
+ fuji_grayscale_marshmallow: { red: 0.960784314, green: 0.972549020, blue: 0.980392157 },
240
+ fuji_grayscale_white: { red: 1.000000000, green: 1.000000000, blue: 1.000000000 }
241
+ }.freeze
8
242
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sheets_v4
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Couball
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-09-22 00:00:00.000000000 Z
11
+ date: 2023-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler-audit
@@ -170,6 +170,20 @@ dependencies:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
172
  version: '7.0'
173
+ - !ruby/object:Gem::Dependency
174
+ name: github_pages_rake_tasks
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '0.1'
180
+ type: :development
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - "~>"
185
+ - !ruby/object:Gem::Version
186
+ version: '0.1'
173
187
  - !ruby/object:Gem::Dependency
174
188
  name: google-apis-sheets_v4
175
189
  requirement: !ruby/object:Gem::Requirement
@@ -198,6 +212,20 @@ dependencies:
198
212
  - - ">="
199
213
  - !ruby/object:Gem::Version
200
214
  version: '0'
215
+ - !ruby/object:Gem::Dependency
216
+ name: json_schemer
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "~>"
220
+ - !ruby/object:Gem::Version
221
+ version: '2.0'
222
+ type: :runtime
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: '2.0'
201
229
  - !ruby/object:Gem::Dependency
202
230
  name: rltk
203
231
  requirement: !ruby/object:Gem::Requirement
@@ -219,6 +247,7 @@ executables: []
219
247
  extensions: []
220
248
  extra_rdoc_files: []
221
249
  files:
250
+ - ".markdownlint.yml"
222
251
  - ".rspec"
223
252
  - ".rubocop.yml"
224
253
  - ".yardopts"
@@ -227,7 +256,10 @@ files:
227
256
  - LICENSE.txt
228
257
  - README.md
229
258
  - Rakefile
259
+ - examples/README.md
230
260
  - lib/sheets_v4.rb
261
+ - lib/sheets_v4/color.rb
262
+ - lib/sheets_v4/validate_api_object.rb
231
263
  - lib/sheets_v4/version.rb
232
264
  homepage: https://github.com/main-branch/sheets_v4
233
265
  licenses: