sheets_db 0.11.0 → 0.13.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: cdf056137eb54d33c6647240ada1498ca2527d44fe68dd8f170882ecff233725
4
- data.tar.gz: 61d76eff207e4d88bbad700ea9be592dbdbac4a2d709a1883c53dbeae055790e
3
+ metadata.gz: a6eb0913dc274c00619b8de23c709d73676e64e233294469c00c2eb549afcfbb
4
+ data.tar.gz: ffeaa1616416edd4fa9529c982fce59f39594ec27b6d43eb7da16c5c086824cb
5
5
  SHA512:
6
- metadata.gz: a589ac3ae9d86b63b65691d12ef212323f1ea9266bb8e2230b67972781ba0ca5ec812f3befc0341f67261e16e70fb1511bce37103583ee452869fef1df7bc24b
7
- data.tar.gz: a71d6cf51c4795e6d4185e27c37a0dadf51ea2ec8fdf55607586e510e3a437723f508a20ed7c52fb50373c98c08e8c0cfa74289b5b3da40414241a0079c520f0
6
+ metadata.gz: 06d3c6c10ed9009cfd370de72fd9afc8b4393b77512149fa6043a04c787086822b9c5fd165f21666c3c6612417a77c279ea6fa2023046b6a565dfe7532264f30
7
+ data.tar.gz: 73b8d7c1d5a7b79061af23414984597a66d1e2accf9e7a59c84a8e58e7e53726e66869dc258f60a74b036993156f14c889583be95cf8eb2f8e18176705113edf
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.0.
1
+ 3.1.
data/Guardfile ADDED
@@ -0,0 +1,70 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ # Note: The cmd option is now required due to the increasing number of ways
19
+ # rspec may be run, below are examples of the most common uses.
20
+ # * bundler: 'bundle exec rspec'
21
+ # * bundler binstubs: 'bin/rspec'
22
+ # * spring: 'bin/rspec' (This will use spring if running and you have
23
+ # installed the spring binstubs per the docs)
24
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
25
+ # * 'just' rspec: 'rspec'
26
+
27
+ guard :rspec, cmd: "bundle exec rspec" do
28
+ require "guard/rspec/dsl"
29
+ dsl = Guard::RSpec::Dsl.new(self)
30
+
31
+ # Feel free to open issues for suggestions and improvements
32
+
33
+ # RSpec files
34
+ rspec = dsl.rspec
35
+ watch(rspec.spec_helper) { rspec.spec_dir }
36
+ watch(rspec.spec_support) { rspec.spec_dir }
37
+ watch(rspec.spec_files)
38
+
39
+ # Ruby files
40
+ ruby = dsl.ruby
41
+ dsl.watch_spec_files_for(ruby.lib_files)
42
+
43
+ # Rails files
44
+ rails = dsl.rails(view_extensions: %w(erb haml slim))
45
+ dsl.watch_spec_files_for(rails.app_files)
46
+ dsl.watch_spec_files_for(rails.views)
47
+
48
+ watch(rails.controllers) do |m|
49
+ [
50
+ rspec.spec.call("routing/#{m[1]}_routing"),
51
+ rspec.spec.call("controllers/#{m[1]}_controller"),
52
+ rspec.spec.call("acceptance/#{m[1]}")
53
+ ]
54
+ end
55
+
56
+ # Rails config changes
57
+ watch(rails.spec_helper) { rspec.spec_dir }
58
+ watch(rails.routes) { "#{rspec.spec_dir}/routing" }
59
+ watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
60
+
61
+ # Capybara features specs
62
+ watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
63
+ watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }
64
+
65
+ # Turnip features and steps
66
+ watch(%r{^spec/acceptance/(.+)\.feature$})
67
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
68
+ Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
69
+ end
70
+ end
@@ -1,18 +1,63 @@
1
1
  module SheetsDB
2
2
  class Collection < Resource
3
+ class SpreadsheetNotFoundError < Resource::ChildResourceNotFoundError; end
4
+
3
5
  set_resource_type GoogleDrive::Collection
4
6
 
5
- def self.has_many(resource, class_name:, resource_type: :subcollections)
6
- unless [:subcollections, :spreadsheets].include?(resource_type)
7
- raise ArgumentError, "resource_type must be :subcollections or :spreadsheets"
7
+ class << self
8
+ def has_many(resource, class_name:, resource_type: :subcollections)
9
+ unless [:subcollections, :spreadsheets].include?(resource_type)
10
+ raise ArgumentError, "resource_type must be :subcollections or :spreadsheets"
11
+ end
12
+ register_association(resource, class_name: class_name, resource_type: resource_type)
13
+ define_method(resource) do
14
+ @associated_resources ||= {}
15
+ @associated_resources[resource] ||= google_drive_resource.send(resource_type).map { |raw|
16
+ Support.constantize(class_name).new(raw)
17
+ }
18
+ end
8
19
  end
9
- register_association(resource, class_name: class_name, resource_type: resource_type)
10
- define_method(resource) do
11
- result = instance_variable_get(:"@#{resource}")
12
- result || instance_variable_set(:"@#{resource}",
13
- google_drive_resource.send(resource_type).map { |raw| Support.constantize(class_name).new(raw) }
14
- )
20
+ end
21
+
22
+ %i[
23
+ spreadsheet
24
+ subcollection
25
+ ].each do |child_resource_type|
26
+ define_method :"google_drive_#{child_resource_type}_by_title" do |title, **kwargs|
27
+ find_child_google_drive_resource_by(type: child_resource_type, title: title, **kwargs)
15
28
  end
16
29
  end
30
+
31
+ def find_spreadsheet(title:)
32
+ find_spreadsheet!(title: title)
33
+ rescue ChildResourceNotFoundError
34
+ nil
35
+ end
36
+
37
+ def find_spreadsheet!(title:)
38
+ find_and_wrap_spreadsheet!(title: title, create: false)
39
+ end
40
+
41
+ def find_or_create_spreadsheet!(title:)
42
+ find_and_wrap_spreadsheet!(title: title, create: true)
43
+ end
44
+
45
+ def find_and_wrap_spreadsheet!(title:, create: false)
46
+ Spreadsheet.new(google_drive_spreadsheet_by_title(title, create: create))
47
+ rescue ChildResourceNotFoundError
48
+ raise SpreadsheetNotFoundError
49
+ end
50
+
51
+ def spreadsheets
52
+ @anonymous_resources ||= {}
53
+ @anonymous_resources[:spreadsheets] ||=
54
+ google_drive_resource.spreadsheets.map { |raw| Spreadsheet.new(raw) }
55
+ end
56
+
57
+ def collections
58
+ @anonymous_resources ||= {}
59
+ @anonymous_resources[:collections] ||=
60
+ google_drive_resource.subcollections.map { |raw| Collection.new(raw) }
61
+ end
17
62
  end
18
- end
63
+ end
@@ -2,6 +2,7 @@ module SheetsDB
2
2
  class Resource
3
3
  class ResourceTypeMismatchError < StandardError; end
4
4
  class CollectionTypeAlreadyRegisteredError < StandardError; end
5
+ class ChildResourceNotFoundError < StandardError; end
5
6
 
6
7
  class << self
7
8
  attr_reader :resource_type
@@ -17,8 +18,8 @@ module SheetsDB
17
18
 
18
19
  def find_by_id(id, session: SheetsDB::Session.default)
19
20
  google_drive_resource = session.raw_file_by_id(id)
20
- if @resource_type && !google_drive_resource.is_a?(@resource_type)
21
- fail(ResourceTypeMismatchError, "The file with id #{id} is not a #{@resource_type}")
21
+ if resource_type && !google_drive_resource.is_a?(resource_type)
22
+ fail(ResourceTypeMismatchError, "The file with id #{id} is not a #{resource_type}")
22
23
  end
23
24
  new(google_drive_resource)
24
25
  end
@@ -26,10 +27,10 @@ module SheetsDB
26
27
  def belongs_to_many(resource, class_name:)
27
28
  register_association(resource, class_name: class_name, resource_type: :parents)
28
29
  define_method(resource) do
29
- result = instance_variable_get(:"@#{resource}")
30
- result || instance_variable_set(:"@#{resource}",
31
- google_drive_resource.parents.map { |id| Support.constantize(class_name).find_by_id(id) }
32
- )
30
+ @associated_resources ||= {}
31
+ @associated_resources[resource] ||= google_drive_resource.parents.map { |id|
32
+ Support.constantize(class_name).find_by_id(id)
33
+ }
33
34
  end
34
35
  end
35
36
 
@@ -43,6 +44,15 @@ module SheetsDB
43
44
  class_name: class_name
44
45
  }
45
46
  end
47
+
48
+ def association_methods_for_type(type)
49
+ raise ArgumentError unless %i[spreadsheet worksheet subcollection].include?(type)
50
+
51
+ google_type = type == :spreadsheet ? :file : type
52
+ create_prefix = type == :worksheet ? :add : :create
53
+
54
+ OpenStruct.new(find: :"#{google_type}_by_title", create: :"#{create_prefix}_#{type}")
55
+ end
46
56
  end
47
57
 
48
58
  extend Forwardable
@@ -56,6 +66,16 @@ module SheetsDB
56
66
  @google_drive_resource = google_drive_resource
57
67
  end
58
68
 
69
+ def reload!
70
+ @associated_resources = nil
71
+ @anonymous_resources = nil
72
+ google_drive_resource.reload_metadata
73
+ end
74
+
75
+ def delete!
76
+ google_drive_resource.delete
77
+ end
78
+
59
79
  def ==(other)
60
80
  other.is_a?(self.class) &&
61
81
  other.google_drive_resource == google_drive_resource
@@ -75,5 +95,14 @@ module SheetsDB
75
95
  updated_at: updated_at
76
96
  }
77
97
  end
98
+
99
+ def find_child_google_drive_resource_by(type:, title:, create: false)
100
+ association_methods = self.class.association_methods_for_type(type)
101
+ child_resource = google_drive_resource.public_send(association_methods.find, title)
102
+ child_resource ||= google_drive_resource.public_send(association_methods.create, title) if create
103
+ raise ChildResourceNotFoundError, [self, type, title] if child_resource.nil?
104
+
105
+ child_resource
106
+ end
78
107
  end
79
108
  end
@@ -1,37 +1,31 @@
1
1
  module SheetsDB
2
2
  class Spreadsheet < Resource
3
3
  class WorksheetAssociationAlreadyRegisteredError < StandardError; end
4
- class WorksheetNotFoundError < StandardError; end
4
+ class WorksheetNotFoundError < Resource::ChildResourceNotFoundError; end
5
+ class LastWorksheetCannotBeDeletedError < StandardError; end
5
6
 
6
7
  set_resource_type GoogleDrive::Spreadsheet
7
8
 
8
- def self.has_many(resource, worksheet_name:, class_name:)
9
- register_worksheet_association(resource, worksheet_name: worksheet_name, class_name: class_name)
10
- create_worksheet_association(resource, worksheet_name: worksheet_name, class_name: class_name)
11
- end
9
+ class << self
10
+ def has_many(resource, worksheet_name:, class_name:)
11
+ register_worksheet_association(resource, worksheet_name: worksheet_name, class_name: class_name)
12
+ create_worksheet_association(resource, worksheet_name: worksheet_name, class_name: class_name)
13
+ end
12
14
 
13
- def self.register_worksheet_association(resource, worksheet_name:, class_name:)
14
- @associations ||= {}
15
- if @associations.fetch(resource, nil)
16
- raise WorksheetAssociationAlreadyRegisteredError
15
+ def register_worksheet_association(resource, worksheet_name:, class_name:)
16
+ @associations ||= {}
17
+ if @associations.fetch(resource, nil)
18
+ raise WorksheetAssociationAlreadyRegisteredError
19
+ end
20
+ @associations[resource] = {
21
+ worksheet_name: worksheet_name,
22
+ class_name: class_name
23
+ }
17
24
  end
18
- @associations[resource] = {
19
- worksheet_name: worksheet_name,
20
- class_name: class_name
21
- }
22
- end
23
25
 
24
- def self.create_worksheet_association(resource, worksheet_name:, class_name:)
25
- define_method(resource) do
26
- @worksheets ||= {}
27
- @worksheets[resource] ||= begin
28
- google_drive_worksheet = google_drive_resource.worksheet_by_title(worksheet_name)
29
- raise WorksheetNotFoundError, worksheet_name if google_drive_worksheet.nil?
30
- Worksheet.new(
31
- spreadsheet: self,
32
- google_drive_resource: google_drive_worksheet,
33
- type: Support.constantize(class_name)
34
- )
26
+ def create_worksheet_association(resource, **kwargs)
27
+ define_method(resource) do
28
+ worksheet_association(resource, **kwargs)
35
29
  end
36
30
  end
37
31
  end
@@ -51,5 +45,65 @@ module SheetsDB
51
45
  def select_from_association(association_name, &block)
52
46
  send(association_name).select(&block)
53
47
  end
48
+
49
+ def worksheet_association(association_name, worksheet_name:, class_name:)
50
+ @associated_resources ||= {}
51
+ @associated_resources[association_name] ||=
52
+ find_or_create_worksheet!(title: worksheet_name, type: Support.constantize(class_name))
53
+ end
54
+
55
+ def worksheets
56
+ @anonymous_resources ||= {}
57
+ @anonymous_resources[:worksheets] ||= google_drive_resource.worksheets.map { |raw|
58
+ set_up_worksheet!(google_drive_resource: raw)
59
+ }
60
+ end
61
+
62
+ def set_up_worksheet!(google_drive_resource:, type: nil)
63
+ wrap_worksheet(google_drive_resource: google_drive_resource, type: type).set_up!
64
+ end
65
+
66
+ def wrap_worksheet(google_drive_resource:, type: nil)
67
+ Worksheet.new(
68
+ google_drive_resource: google_drive_resource,
69
+ spreadsheet: self,
70
+ type: type
71
+ )
72
+ end
73
+
74
+ def find_worksheet(title:, type: nil)
75
+ find_worksheet!(title: title, type: type)
76
+ rescue WorksheetNotFoundError
77
+ nil
78
+ end
79
+
80
+ def find_worksheet!(title:, type: nil)
81
+ find_and_setup_worksheet!(title: title, type: type, create: false)
82
+ end
83
+
84
+ def find_or_create_worksheet!(title:, type: nil)
85
+ find_and_setup_worksheet!(title: title, type: type, create: true)
86
+ end
87
+
88
+ def find_and_setup_worksheet!(title:, type: nil, create: false)
89
+ resource = google_drive_worksheet_by_title(title, create: create)
90
+ set_up_worksheet!(google_drive_resource: resource, type: type)
91
+ rescue ChildResourceNotFoundError
92
+ raise WorksheetNotFoundError
93
+ end
94
+
95
+ def clean_up_default_worksheet!(force: false)
96
+ default_sheet = google_drive_resource.worksheet_by_title("Sheet1")
97
+ return unless default_sheet
98
+
99
+ raise LastWorksheetCannotBeDeletedError if google_drive_resource.worksheets.count == 1
100
+
101
+ wrap_worksheet(google_drive_resource: default_sheet).
102
+ delete_google_drive_resource!(force: force)
103
+ end
104
+
105
+ def google_drive_worksheet_by_title(title, **kwargs)
106
+ find_child_google_drive_resource_by(type: :worksheet, title: title, **kwargs)
107
+ end
54
108
  end
55
109
  end
@@ -1,3 +1,3 @@
1
1
  module SheetsDB
2
- VERSION = "0.11.0"
2
+ VERSION = "0.13.0"
3
3
  end
@@ -172,6 +172,7 @@ module SheetsDB
172
172
  def reload!
173
173
  worksheet.reload!
174
174
  reset_attributes_and_associations_cache
175
+ self
175
176
  end
176
177
 
177
178
  def save!
@@ -179,6 +180,7 @@ module SheetsDB
179
180
  worksheet.update_attributes_at_row_position(staged_attributes, row_position: row_position)
180
181
  save_changed_foreign_items!
181
182
  reset_attributes_and_associations_cache
183
+ self
182
184
  end
183
185
 
184
186
  def assign_next_row_position_if_not_set
@@ -192,6 +194,7 @@ module SheetsDB
192
194
  def reset_attributes_and_associations_cache
193
195
  @loaded_attributes = {}
194
196
  @loaded_associations = {}
197
+ self
195
198
  end
196
199
 
197
200
  def staged_attributes
@@ -1,21 +1,44 @@
1
+ require 'bigdecimal/util'
1
2
  require_relative "worksheet/column"
2
3
  require_relative "worksheet/row"
3
4
 
4
5
  module SheetsDB
5
6
  class Worksheet
6
7
  class ColumnNotFoundError < StandardError; end
8
+ class WorksheetContainsDataError < StandardError; end
7
9
 
8
10
  include Enumerable
11
+ extend Forwardable
9
12
 
10
- attr_reader :spreadsheet, :google_drive_resource, :type, :synchronizing
13
+ attr_reader :spreadsheet, :google_drive_resource, :synchronizing
11
14
 
12
- def initialize(spreadsheet:, google_drive_resource:, type:)
15
+ def_delegator :google_drive_resource, :title
16
+
17
+ def initialize(spreadsheet:, google_drive_resource:, type: nil)
13
18
  @spreadsheet = spreadsheet
14
19
  @google_drive_resource = google_drive_resource
15
20
  @type = type
16
21
  @synchronizing = true
17
22
  end
18
23
 
24
+ def set_up!
25
+ if google_drive_resource.num_rows == 0
26
+ registered_column_names = attribute_definitions.map { |name, definition| definition[:column_name] }
27
+ write_matrix!([registered_column_names])
28
+ end
29
+ self
30
+ end
31
+
32
+ def type
33
+ @type || @generated_type ||= begin
34
+ Class.new(Row).tap { |generated_type_class|
35
+ column_names.each do |name|
36
+ generated_type_class.attribute name.to_sym
37
+ end
38
+ }
39
+ end
40
+ end
41
+
19
42
  def ==(other)
20
43
  other.is_a?(self.class) &&
21
44
  other.google_drive_resource == google_drive_resource &&
@@ -31,7 +54,8 @@ module SheetsDB
31
54
  def columns
32
55
  @columns ||= begin
33
56
  {}.tap { |directory|
34
- google_drive_resource.rows.first.each_with_index do |name, i|
57
+ header_row = google_drive_resource.rows.first || []
58
+ header_row.each_with_index do |name, i|
35
59
  unless name == ""
36
60
  directory[name] = Column.new(name: name, column_position: i + 1)
37
61
  end
@@ -98,12 +122,20 @@ module SheetsDB
98
122
 
99
123
  def update_attributes_at_row_position(staged_attributes, row_position:)
100
124
  staged_attributes.each do |attribute_name, value|
101
- attribute_definition, column = get_definition_and_column(attribute_name)
102
- raise ColumnNotFoundError, column unless column
103
- assignment_value = attribute_definition[:multiple] ? value.join(",") : value
104
- google_drive_resource[row_position, column.column_position] = assignment_value
125
+ update_attribute_at_row_position(
126
+ attribute_name: attribute_name,
127
+ value: value,
128
+ row_position: row_position
129
+ )
105
130
  end
106
- google_drive_resource.synchronize if synchronizing
131
+ synchronize! if synchronizing
132
+ end
133
+
134
+ def update_attribute_at_row_position(attribute_name:, value:, row_position:)
135
+ attribute_definition, column = get_definition_and_column(attribute_name)
136
+ raise ColumnNotFoundError, column unless column
137
+ assignment_value = attribute_definition[:multiple] ? value.join(",") : value
138
+ google_drive_resource[row_position, column.column_position] = assignment_value
107
139
  end
108
140
 
109
141
  def next_available_row_position
@@ -163,7 +195,11 @@ module SheetsDB
163
195
  end
164
196
 
165
197
  def reload!
198
+ @columns = nil
199
+ @existing_raw_data = nil
200
+ @generated_type = nil
166
201
  google_drive_resource.reload
202
+ self
167
203
  end
168
204
 
169
205
  def convert_to_boolean(raw_value)
@@ -180,8 +216,8 @@ module SheetsDB
180
216
  converted_value = case attribute_definition[:type].to_s
181
217
  when "Integer"
182
218
  raw_value.to_i
183
- when "Float"
184
- raw_value.to_f
219
+ when "Decimal"
220
+ raw_value.to_d
185
221
  when "DateTime"
186
222
  DateTime.strptime(raw_value, "%m/%d/%Y %H:%M:%S")
187
223
  when "Boolean"
@@ -205,9 +241,66 @@ module SheetsDB
205
241
  def transaction
206
242
  disable_synchronization!
207
243
  yield
208
- google_drive_resource.synchronize
244
+ synchronize!
209
245
  ensure
210
246
  enable_synchronization!
211
247
  end
248
+
249
+ def delete_google_drive_resource!(force: false)
250
+ raise WorksheetContainsDataError if google_drive_resource.num_rows.nonzero? && !force
251
+
252
+ google_drive_resource.delete
253
+ @google_drive_resource = nil
254
+ spreadsheet.reload!
255
+ end
256
+
257
+ def truncate!
258
+ clear_google_drive_resource!
259
+ set_up!
260
+ reload!
261
+ end
262
+
263
+ def write_matrix(matrix, rewrite: false, save: false)
264
+ clear_google_drive_resource if rewrite
265
+ google_drive_resource.update_cells(1, 1, matrix)
266
+ synchronize! if save
267
+ self
268
+ end
269
+
270
+ def write_matrix!(matrix, **options)
271
+ write_matrix(matrix, **options.merge(save: true))
272
+ end
273
+
274
+ def write_raw_data(data, **options)
275
+ raise ArgumentError, "mismatched keys" if data.map(&:keys).uniq.count > 1
276
+
277
+ write_matrix(data.map(&:values).prepend(data.first.keys), **options)
278
+ end
279
+
280
+ def write_raw_data!(data, **options)
281
+ write_raw_data(data, **options.merge(save: true))
282
+ end
283
+
284
+ def clear_google_drive_resource(save: false)
285
+ empty_matrix = Array.new(google_drive_resource.num_rows, Array.new(google_drive_resource.num_cols))
286
+ write_matrix(empty_matrix, save: save)
287
+ end
288
+
289
+ def clear_google_drive_resource!
290
+ clear_google_drive_resource(save: true)
291
+ end
292
+
293
+ def synchronize!
294
+ google_drive_resource.synchronize
295
+ @existing_raw_data = nil
296
+ self
297
+ end
298
+
299
+ def existing_raw_data
300
+ @existing_raw_data ||= begin
301
+ rows = google_drive_resource.rows
302
+ rows.drop(1).map { |row| Hash[rows.first.zip(row)] }
303
+ end
304
+ end
212
305
  end
213
306
  end
data/sheets_db.gemspec CHANGED
@@ -20,8 +20,9 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_dependency "google_drive", "~> 3.0"
22
22
 
23
- spec.add_development_dependency "bundler", "~> 2.1"
23
+ spec.add_development_dependency "bundler", "~> 2.4"
24
24
  spec.add_development_dependency "rake", "~> 13"
25
- spec.add_development_dependency "rspec", "~> 3.10"
25
+ spec.add_development_dependency "rspec", "~> 3.11"
26
26
  spec.add_development_dependency "simplecov"
27
+ spec.add_development_dependency "guard-rspec"
27
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sheets_db
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ravi Gadad
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-17 00:00:00.000000000 Z
11
+ date: 2024-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google_drive
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.1'
33
+ version: '2.4'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.1'
40
+ version: '2.4'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.10'
61
+ version: '3.11'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.10'
68
+ version: '3.11'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description:
84
98
  email:
85
99
  - ravi@ablschools.com
@@ -93,6 +107,7 @@ files:
93
107
  - ".travis.yml"
94
108
  - CODE_OF_CONDUCT.md
95
109
  - Gemfile
110
+ - Guardfile
96
111
  - LICENSE.txt
97
112
  - README.md
98
113
  - Rakefile
@@ -138,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
153
  - !ruby/object:Gem::Version
139
154
  version: '0'
140
155
  requirements: []
141
- rubygems_version: 3.2.32
156
+ rubygems_version: 3.3.26
142
157
  signing_key:
143
158
  specification_version: 4
144
159
  summary: Adapter for pseudo-relational data stored in Google Sheets