sheets_db 0.12.0 → 0.14.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: 8186e2c37fc147e8bcc4fed8c4bf288b05dde2466c9145e24882d7e1c41d3d35
4
- data.tar.gz: cdaf52978086b08fed7cd9635aed44ae2f06bfb756058f1eb4d4fc0bf73e8945
3
+ metadata.gz: d020639fc0646a740ab9afda00ac3bf8098835cc64c83789a08e323e4021f365
4
+ data.tar.gz: 6e9eed146d5b2e450f98830a02c6b882a9e415ba04a8c702a4df4757c6d2a1aa
5
5
  SHA512:
6
- metadata.gz: 89fd0245435dcfe13010330ca1220bc1d1ec1082333583021cb65f1d74857f6886eebf4325d7f1107ccdc3a406eb58877c914ef3bbdab8b9c4f1e98ffedb7e70
7
- data.tar.gz: 2575c45b0f15e24cdbe8296d79a0429eb8120a41414cf112328106b650c70142df3312de2e1d86ffe63ae7c65e32f839bf413ee94c3ea647deae2d2eb692d77a
6
+ metadata.gz: a82534bb2ee225da6656ce6a511e97fc3174376bde01af3c414e37d6336a756f0658b36f6c0b87426ac83bb38fed4874334fdc878ea02adcf7465d217789d223
7
+ data.tar.gz: 30012de7ca8856ef2b345e6e728585d53fa1e2e1a786424b62ed62053ebae67f1acf2afd0659fc9600f03764e951bf8084bde66eb73df0f392fb04f12ff723cd
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,5 +1,7 @@
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
7
  class << self
@@ -26,6 +28,26 @@ module SheetsDB
26
28
  end
27
29
  end
28
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
+
29
51
  def spreadsheets
30
52
  @anonymous_resources ||= {}
31
53
  @anonymous_resources[:spreadsheets] ||=
@@ -16,10 +16,26 @@ module SheetsDB
16
16
  @resource_type = resource_type
17
17
  end
18
18
 
19
+ def find(id_or_url, session: SheetsDB::Session.default)
20
+ find_by_url(id_or_url, session: session)
21
+ rescue SheetsDB::Session::InvalidGoogleDriveUrlError
22
+ find_by_id(id_or_url, session: session)
23
+ end
24
+
25
+ def find_by_url(url, session: SheetsDB::Session.default)
26
+ wrap_google_drive_resource(session.raw_file_by_url(url))
27
+ end
28
+
19
29
  def find_by_id(id, session: SheetsDB::Session.default)
20
- google_drive_resource = session.raw_file_by_id(id)
30
+ wrap_google_drive_resource(session.raw_file_by_id(id))
31
+ end
32
+
33
+ def wrap_google_drive_resource(google_drive_resource)
21
34
  if resource_type && !google_drive_resource.is_a?(resource_type)
22
- fail(ResourceTypeMismatchError, "The file with id #{id} is not a #{resource_type}")
35
+ fail(
36
+ ResourceTypeMismatchError,
37
+ "The file #{google_drive_resource.human_url} is not a #{resource_type}"
38
+ )
23
39
  end
24
40
  new(google_drive_resource)
25
41
  end
@@ -4,6 +4,7 @@ module SheetsDB
4
4
  class Session
5
5
  class IllegalDefaultError < StandardError; end
6
6
  class NoDefaultSetError < StandardError; end
7
+ class InvalidGoogleDriveUrlError < ArgumentError; end
7
8
 
8
9
  def self.default=(default)
9
10
  unless default.is_a?(self)
@@ -30,5 +31,12 @@ module SheetsDB
30
31
  def raw_file_by_id(id)
31
32
  @google_drive_session.file_by_id(id)
32
33
  end
34
+
35
+ def raw_file_by_url(url)
36
+ @google_drive_session.file_by_url(url)
37
+ rescue GoogleDrive::Error => e
38
+ (raise InvalidGoogleDriveUrlError, url) if e.message.match(/not a known Google Drive URL/)
39
+ raise
40
+ end
33
41
  end
34
- end
42
+ end
@@ -1,7 +1,8 @@
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
 
@@ -59,16 +60,46 @@ module SheetsDB
59
60
  end
60
61
 
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)
62
67
  Worksheet.new(
63
68
  google_drive_resource: google_drive_resource,
64
69
  spreadsheet: self,
65
70
  type: type
66
- ).set_up!
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)
67
82
  end
68
83
 
69
84
  def find_or_create_worksheet!(title:, type: nil)
70
- resource = google_drive_worksheet_by_title(title, create: true)
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)
71
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)
72
103
  end
73
104
 
74
105
  def google_drive_worksheet_by_title(title, **kwargs)
@@ -1,3 +1,3 @@
1
1
  module SheetsDB
2
- VERSION = "0.12.0"
2
+ VERSION = "0.14.0"
3
3
  end
@@ -1,18 +1,22 @@
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, :worksheet_title, :google_drive_resource, :synchronizing
13
+ attr_reader :spreadsheet, :google_drive_resource, :synchronizing
14
+
15
+ def_delegator :google_drive_resource, :title
11
16
 
12
17
  def initialize(spreadsheet:, google_drive_resource:, type: nil)
13
18
  @spreadsheet = spreadsheet
14
19
  @google_drive_resource = google_drive_resource
15
- @worksheet_title = google_drive_resource.title
16
20
  @type = type
17
21
  @synchronizing = true
18
22
  end
@@ -212,8 +216,8 @@ module SheetsDB
212
216
  converted_value = case attribute_definition[:type].to_s
213
217
  when "Integer"
214
218
  raw_value.to_i
215
- when "Float"
216
- raw_value.to_f
219
+ when "Decimal"
220
+ raw_value.to_d
217
221
  when "DateTime"
218
222
  DateTime.strptime(raw_value, "%m/%d/%Y %H:%M:%S")
219
223
  when "Boolean"
@@ -242,7 +246,9 @@ module SheetsDB
242
246
  enable_synchronization!
243
247
  end
244
248
 
245
- def delete_google_drive_resource!
249
+ def delete_google_drive_resource!(force: false)
250
+ raise WorksheetContainsDataError if google_drive_resource.num_rows.nonzero? && !force
251
+
246
252
  google_drive_resource.delete
247
253
  @google_drive_resource = nil
248
254
  spreadsheet.reload!
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
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.12.0
4
+ version: 0.14.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-02-16 00:00:00.000000000 Z
11
+ date: 2024-08-20 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
@@ -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