skypager 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/Rakefile +21 -0
- data/bin/skypager +17 -0
- data/examples/.gitignore +4 -0
- data/examples/blog-site/.gitignore +18 -0
- data/examples/blog-site/.pryrc +4 -0
- data/examples/blog-site/Gemfile +8 -0
- data/examples/blog-site/config.rb +17 -0
- data/examples/blog-site/data/dropbox.json +1 -0
- data/examples/blog-site/source/images/background.png +0 -0
- data/examples/blog-site/source/images/middleman.png +0 -0
- data/examples/blog-site/source/index.html.erb +10 -0
- data/examples/blog-site/source/javascripts/all.js +1 -0
- data/examples/blog-site/source/layouts/layout.erb +19 -0
- data/examples/blog-site/source/posts/introduction-to-skypager.html.md +23 -0
- data/examples/blog-site/source/posts/skypager-and-dnsimple-and-amazon-web-services-combo.html.md +9 -0
- data/examples/blog-site/source/stylesheets/all.css +55 -0
- data/examples/blog-site/source/stylesheets/normalize.css +375 -0
- data/examples/gallery-site/.gitignore +18 -0
- data/examples/gallery-site/.pryrc +4 -0
- data/examples/gallery-site/Gemfile +11 -0
- data/examples/gallery-site/config.rb +38 -0
- data/examples/gallery-site/data/dropbox.json +1 -0
- data/examples/gallery-site/data/galleries.json +1 -0
- data/examples/gallery-site/source/gallery.html.erb +7 -0
- data/examples/gallery-site/source/images/background.png +0 -0
- data/examples/gallery-site/source/images/galleries/cristian-gallery-1/001.jpg +0 -0
- data/examples/gallery-site/source/images/galleries/cristian-gallery-1/002.jpg +0 -0
- data/examples/gallery-site/source/images/galleries/cristian-gallery-1/003.jpg +0 -0
- data/examples/gallery-site/source/images/galleries/cristian-gallery-1/004.jpg +0 -0
- data/examples/gallery-site/source/images/galleries/luca-gallery-1/001.jpg +0 -0
- data/examples/gallery-site/source/images/galleries/luca-gallery-1/002.JPG +0 -0
- data/examples/gallery-site/source/images/galleries/luca-gallery-1/003.jpg +0 -0
- data/examples/gallery-site/source/images/galleries/luca-gallery-1/004.JPG +0 -0
- data/examples/gallery-site/source/images/middleman.png +0 -0
- data/examples/gallery-site/source/index.html.erb +10 -0
- data/examples/gallery-site/source/javascripts/all.js +1 -0
- data/examples/gallery-site/source/layouts/layout.erb +20 -0
- data/examples/gallery-site/source/stylesheets/all.css +0 -0
- data/examples/gallery-site/source/stylesheets/normalize.css +375 -0
- data/examples/gallery-site/source/tutorial.md +151 -0
- data/lib/skypager.rb +92 -0
- data/lib/skypager/build_server.rb +17 -0
- data/lib/skypager/cli/commands/config.rb +58 -0
- data/lib/skypager/cli/commands/create.rb +98 -0
- data/lib/skypager/cli/commands/deploy.rb +30 -0
- data/lib/skypager/cli/commands/edit.rb +32 -0
- data/lib/skypager/cli/commands/list.rb +12 -0
- data/lib/skypager/cli/commands/setup.rb +124 -0
- data/lib/skypager/cli/commands/sync.rb +18 -0
- data/lib/skypager/configuration.rb +173 -0
- data/lib/skypager/data.rb +8 -0
- data/lib/skypager/data/excel_spreadsheet.rb +8 -0
- data/lib/skypager/data/google_spreadsheet.rb +225 -0
- data/lib/skypager/data/request.rb +12 -0
- data/lib/skypager/data/source.rb +171 -0
- data/lib/skypager/data/source_routes_proxy.rb +30 -0
- data/lib/skypager/dns.rb +65 -0
- data/lib/skypager/extension.rb +203 -0
- data/lib/skypager/middleman/commands/data.rb +0 -0
- data/lib/skypager/middleman/commands/deploy.rb +0 -0
- data/lib/skypager/middleman/commands/sync.rb +0 -0
- data/lib/skypager/site.rb +208 -0
- data/lib/skypager/sync.rb +23 -0
- data/lib/skypager/sync/amazon.rb +171 -0
- data/lib/skypager/sync/dropbox.rb +173 -0
- data/lib/skypager/sync/dropbox/delta.rb +67 -0
- data/lib/skypager/sync/folder.rb +235 -0
- data/lib/skypager/sync/google.rb +143 -0
- data/lib/skypager/tar.rb +77 -0
- data/lib/skypager/version.rb +3 -0
- data/skypager.gemspec +40 -0
- data/spec/lib/skypager/configuration_spec.rb +5 -0
- data/spec/lib/skypager/data_spec.rb +5 -0
- data/spec/lib/skypager/site_spec.rb +5 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/json_helper.rb +7 -0
- metadata +383 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
edit_spreadsheet_command = lambda do |c|
|
2
|
+
c.syntax = "skypager edit datasource NAME"
|
3
|
+
c.description = "Open up the data source editor"
|
4
|
+
|
5
|
+
c.action do |args, options|
|
6
|
+
require 'launchy'
|
7
|
+
require 'middleman-core'
|
8
|
+
|
9
|
+
name = args.first
|
10
|
+
|
11
|
+
if defined?(::Middleman)
|
12
|
+
app = ::Middleman::Application.server.inst do
|
13
|
+
set :environment, 'development'
|
14
|
+
end
|
15
|
+
|
16
|
+
if !name
|
17
|
+
names = app.data_sources.keys.map(&:to_s)
|
18
|
+
name = choose("Which data source?", *names)
|
19
|
+
end
|
20
|
+
|
21
|
+
source = app.data_sources[name.to_sym]
|
22
|
+
|
23
|
+
if source
|
24
|
+
Launchy.open(source.edit_url)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
command "edit data source" do |c|
|
31
|
+
edit_spreadsheet_command.call(c)
|
32
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
command 'list spreadsheets' do |c|
|
2
|
+
c.syntax = 'skypager list:spreadsheets [options]'
|
3
|
+
c.description = 'list available spreadsheets to use with skypager '
|
4
|
+
|
5
|
+
c.action do |_args, _options|
|
6
|
+
|
7
|
+
Skypager::Sync::Google.setup
|
8
|
+
Skypager::Sync.google.spreadsheets.map {|s| puts [s.key,s.title].join("\t\t") }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
|
@@ -0,0 +1,124 @@
|
|
1
|
+
command 'setup' do |c|
|
2
|
+
c.syntax = 'skypager setup [options]'
|
3
|
+
c.description = 'setup the integrations for skypager to work'
|
4
|
+
|
5
|
+
c.option '--skip-dropbox', nil, 'Skip dropbox setup'
|
6
|
+
c.option '--skip-google', nil, 'Skip google setup'
|
7
|
+
c.option '--skip-amazon', nil, 'Skip amazon setup'
|
8
|
+
c.option '--skip-dns', nil, 'Skip dns setup'
|
9
|
+
|
10
|
+
c.action do |args, options|
|
11
|
+
Skypager::Sync::Dropbox.setup unless options.skip_dropbox || Skypager.config.dropbox_setup?
|
12
|
+
Skypager::Sync::Google.setup unless options.skip_google || Skypager.config.google_setup?
|
13
|
+
Skypager::Sync::Amazon.setup unless options.skip_amazon || Skypager.config.amazon_setup?
|
14
|
+
|
15
|
+
require 'dnsimple'
|
16
|
+
Skypager.dns.setup unless options.skip_dns || Skypager.config.dnsimple_setup?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
command 'setup amazon' do |c|
|
21
|
+
c.syntax = 'skypager setup amazon [options]'
|
22
|
+
c.description = 'Setup amazon integration'
|
23
|
+
|
24
|
+
c.option '--access-key-id STRING', String, 'What is the AWS access key id?'
|
25
|
+
c.option '--secret-access-key STRING', String, 'What is the AWS secret access key?'
|
26
|
+
c.option '--create-bucket STRING', String, 'What is the bucket name?'
|
27
|
+
|
28
|
+
c.action do |args, options|
|
29
|
+
Skypager::Sync::Amazon.setup(access_key_id: options.access_key_id,
|
30
|
+
secret_access_key: options.secret_access_key)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
command 'setup deployment' do |c|
|
36
|
+
c.syntax = 'skypager setup deployment [options]'
|
37
|
+
c.description = 'Setup AWS deployment / hosting'
|
38
|
+
|
39
|
+
c.option '--access-key-id STRING', String, 'What is the AWS access key id?'
|
40
|
+
c.option '--secret-access-key STRING', String, 'What is the AWS secret access key?'
|
41
|
+
c.option '--create-bucket STRING', String, 'What is the bucket name?'
|
42
|
+
|
43
|
+
c.action do |args, options|
|
44
|
+
Skypager::Sync::Amazon.setup(access_key_id: options.access_key_id,
|
45
|
+
secret_access_key: options.secret_access_key)
|
46
|
+
|
47
|
+
|
48
|
+
app = Skypager.app
|
49
|
+
|
50
|
+
if !Skypager.config.dnsimple_setup?
|
51
|
+
if agree("Do you want to setup DNSimple integration?")
|
52
|
+
Skypager.dns.setup()
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
custom_domain = app.deploy_options[:custom_domain] || options.custom_domain || ask("Enter a custom domain name to deploy to. Leave blank if you don't want to use this.")
|
57
|
+
|
58
|
+
if custom_domain.to_s.length > 0
|
59
|
+
app.site.set :custom_domain, custom_domain
|
60
|
+
app.site.set :use_cdn, true
|
61
|
+
@custom_domain = custom_domain
|
62
|
+
end
|
63
|
+
|
64
|
+
unless @custom_domain || app.deploy_options[:use_cdn] == true
|
65
|
+
if agree("Do you want to use a CDN? Answer yes if you want to use a custom domain, or SSL for this site")
|
66
|
+
app.site.set :use_cdn, true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
bucket_name = app.deploy_options[:bucket_name] || options.create_bucket || ask("Enter a name for this bucket. Leave blank to use #{ app.site.name }.#{ Skypager.config.domain}")
|
71
|
+
bucket_name = app.site_name + "." + Skypager.config.domain if bucket_name.to_s.length == 0
|
72
|
+
|
73
|
+
if bucket_name
|
74
|
+
if bucket = Skypager.amazon.find_or_create_bucket(bucket_name)
|
75
|
+
app.site.set :bucket_key, bucket.key
|
76
|
+
app.site.set :bucket_name, bucket.key
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
config_path = Pathname(app.root).join("config.rb")
|
81
|
+
config_text = config_path.read rescue ""
|
82
|
+
|
83
|
+
app.site.after_setup
|
84
|
+
|
85
|
+
unless config_text.match(/deploy_to\(\:amazon/)
|
86
|
+
puts "Adding the following to your config.rb:\n\n\t#{ line = app.site.deploy_options_config_string }"
|
87
|
+
config_path.open("a+") {|fh| fh.write(line) }
|
88
|
+
end
|
89
|
+
|
90
|
+
site = app.site
|
91
|
+
|
92
|
+
puts "Site Info:"
|
93
|
+
puts "Bucket Name: #{ site.bucket_name }"
|
94
|
+
puts "Bucket URL: #{ site.bucket_url }"
|
95
|
+
puts "CDN URL: #{ site.cname_value }" if site.has_cdn?
|
96
|
+
puts "Custom Domain: #{ site.custom_domain }" if site.custom_domain?
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
command 'setup dropbox' do |c|
|
101
|
+
c.syntax = 'skypager setup dropbox [options]'
|
102
|
+
c.description = 'Setup dropbox sync'
|
103
|
+
|
104
|
+
c.option '--app-key STRING', String, 'What is the dropbox app key?'
|
105
|
+
c.option '--app-secret STRING', String, 'What is the dropbox app secret?'
|
106
|
+
|
107
|
+
c.action do |args, options|
|
108
|
+
Skypager::Sync::Dropbox.setup(dropbox_app_key: options.app_key,
|
109
|
+
dropbox_app_secret: options.app_secret)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
command 'setup google' do |c|
|
114
|
+
c.syntax = 'skypager setup google [options]'
|
115
|
+
c.description = 'Setup google sync'
|
116
|
+
|
117
|
+
c.option '--client-id STRING', String, 'What is the google app client id?'
|
118
|
+
c.option '--client-secret STRING', String, 'What is the google app client secret?'
|
119
|
+
|
120
|
+
c.action do |args, options|
|
121
|
+
Skypager::Sync::Google.setup(client_id: options.client_id,
|
122
|
+
client_secret: options.client_secret)
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
command 'sync' do |c|
|
2
|
+
c.action do |args, options|
|
3
|
+
app = ::Middleman::Application.server.inst do
|
4
|
+
set :environment, 'development'
|
5
|
+
end
|
6
|
+
|
7
|
+
app.synced_folders.each do |name, folder|
|
8
|
+
puts "Syncing #{ name }"
|
9
|
+
folder.sync()
|
10
|
+
end
|
11
|
+
|
12
|
+
app.data_sources.each do |name, source|
|
13
|
+
source.refresh
|
14
|
+
source.save_to_disk unless source.persisted?
|
15
|
+
data.callbacks(name, -> { source.data })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Skypager
|
5
|
+
class Configuration
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
DefaultSettings = {
|
9
|
+
github_username: '',
|
10
|
+
github_api_token: '',
|
11
|
+
|
12
|
+
dnsimple_api_token: '',
|
13
|
+
dnsimple_username: '',
|
14
|
+
|
15
|
+
dropbox_app_key: '',
|
16
|
+
dropbox_app_secret: '',
|
17
|
+
dropbox_app_type: 'sandbox',
|
18
|
+
dropbox_client_token: '',
|
19
|
+
dropbox_client_secret: '',
|
20
|
+
|
21
|
+
aws_access_key_id: '',
|
22
|
+
aws_secret_access_key: '',
|
23
|
+
|
24
|
+
google_client_id: '',
|
25
|
+
google_client_secret: '',
|
26
|
+
google_refresh_token: '',
|
27
|
+
google_access_token: '',
|
28
|
+
|
29
|
+
domain: "skypager.io",
|
30
|
+
|
31
|
+
sites_directory: { }
|
32
|
+
}
|
33
|
+
|
34
|
+
def self.method_missing(meth, *args, &block)
|
35
|
+
if instance.respond_to?(meth)
|
36
|
+
return instance.send meth, *args, &block
|
37
|
+
end
|
38
|
+
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def method_missing(meth, *args, &block)
|
43
|
+
if current.key?(meth.to_s)
|
44
|
+
return current.fetch(meth)
|
45
|
+
end
|
46
|
+
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize!
|
51
|
+
FileUtils.mkdir_p home_config_path.dirname
|
52
|
+
end
|
53
|
+
|
54
|
+
def dnsimple_setup?
|
55
|
+
dnsimple_api_token.to_s.length > 0 && dnsimple_username.to_s.length > 0
|
56
|
+
end
|
57
|
+
|
58
|
+
def dropbox_setup?
|
59
|
+
dropbox_app_key.to_s.length > 0 && dropbox_app_secret.to_s.length > 0
|
60
|
+
end
|
61
|
+
|
62
|
+
def google_setup?
|
63
|
+
google_client_secret.to_s.length > 0 && google_client_id.to_s.length > 0
|
64
|
+
end
|
65
|
+
|
66
|
+
def amazon_setup?
|
67
|
+
aws_access_key_id.to_s.length > 0 && aws_secret_access_key.to_s.length > 0
|
68
|
+
end
|
69
|
+
|
70
|
+
def show
|
71
|
+
current.each do |p|
|
72
|
+
key, value = p
|
73
|
+
|
74
|
+
unless key == 'sites_directory'
|
75
|
+
puts "#{key}: #{ value.inspect }"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def current
|
81
|
+
@current ||= begin
|
82
|
+
home_config.merge(cwd_config)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def current_config
|
87
|
+
cwd_config_path.exist? ? cwd_config : home_config
|
88
|
+
end
|
89
|
+
|
90
|
+
def get(setting)
|
91
|
+
setting = setting.to_s.downcase
|
92
|
+
current_config[setting]
|
93
|
+
end
|
94
|
+
|
95
|
+
def set(setting, value, persist = true, options={})
|
96
|
+
setting = setting.to_s.downcase
|
97
|
+
cfg = options[:global] ? home_config : current_config
|
98
|
+
cfg[setting] = value
|
99
|
+
save! if persist == true
|
100
|
+
value
|
101
|
+
end
|
102
|
+
|
103
|
+
def unset(setting, persist = true)
|
104
|
+
current_config.delete(setting)
|
105
|
+
save! if persist == true
|
106
|
+
end
|
107
|
+
|
108
|
+
def current
|
109
|
+
defaults = DefaultSettings.dup
|
110
|
+
Hashie::Mash.new(defaults.merge(home_config.merge(cwd_config).merge(applied_config)))
|
111
|
+
end
|
112
|
+
|
113
|
+
def apply_config_from_path(path)
|
114
|
+
path = Pathname(path)
|
115
|
+
parsed = JSON.parse(path.read) rescue {}
|
116
|
+
applied_config.merge!(parsed)
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
|
120
|
+
def save!
|
121
|
+
save_home_config
|
122
|
+
save_cwd_config
|
123
|
+
end
|
124
|
+
|
125
|
+
def save_cwd_config
|
126
|
+
return nil unless cwd_config_path.exist?
|
127
|
+
|
128
|
+
File.open(cwd_config_path, 'w+') do |fh|
|
129
|
+
fh.write JSON.generate(cwd_config.to_hash)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def save_home_config
|
134
|
+
File.open(home_config_path, 'w+') do |fh|
|
135
|
+
fh.write JSON.generate(home_config.to_hash)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Applied config is configuration values passed in context
|
140
|
+
# usually from the cli, but also in the unit tests
|
141
|
+
def applied_config
|
142
|
+
@applied_config ||= {}
|
143
|
+
end
|
144
|
+
|
145
|
+
def cwd_config
|
146
|
+
@cwd_config ||= begin
|
147
|
+
(cwd_config_path.exist? rescue false) ? JSON.parse(cwd_config_path.read) : {}
|
148
|
+
rescue
|
149
|
+
{}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def home_config
|
154
|
+
@home_config ||= begin
|
155
|
+
(home_config_path.exist? rescue false) ? JSON.parse(home_config_path.read) : {}
|
156
|
+
rescue
|
157
|
+
{}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def home_folder
|
162
|
+
Pathname(ENV['HOME']).join('.skypager')
|
163
|
+
end
|
164
|
+
|
165
|
+
def home_config_path
|
166
|
+
home_folder.join('config.json')
|
167
|
+
end
|
168
|
+
|
169
|
+
def cwd_config_path
|
170
|
+
Pathname(Dir.pwd).join('skypager.json')
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
module Skypager
|
2
|
+
module Data
|
3
|
+
class GoogleSpreadsheet < Source
|
4
|
+
|
5
|
+
requires :key
|
6
|
+
|
7
|
+
attr_accessor :key,
|
8
|
+
:session,
|
9
|
+
:name
|
10
|
+
|
11
|
+
def initialize name, options={}
|
12
|
+
@options = options
|
13
|
+
|
14
|
+
if name.is_a?(GoogleDrive::Spreadsheet)
|
15
|
+
@spreadsheet = name
|
16
|
+
@name = @spreadsheet.title
|
17
|
+
@key = @spreadsheet.key
|
18
|
+
end
|
19
|
+
|
20
|
+
@key ||= options[:key]
|
21
|
+
@session ||= options.fetch(:session) { Skypager::Sync.google.api }
|
22
|
+
|
23
|
+
ensure_valid_options!
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.create_from_file(path, title)
|
27
|
+
if find_by_title(title)
|
28
|
+
raise 'Spreadsheet with this title already exists'
|
29
|
+
end
|
30
|
+
|
31
|
+
session.upload_from_file(path, title, :content_type => "text/csv")
|
32
|
+
|
33
|
+
find_by_title(title)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.[](key_or_title)
|
37
|
+
find_by_key(key_or_title) || find_by_title(key_or_title)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.find_by_key(key)
|
41
|
+
sheet = session_spreadsheets.detect do |spreadsheet|
|
42
|
+
spreadsheet.key == key
|
43
|
+
end
|
44
|
+
|
45
|
+
sheet && new(sheet, session: Skypager.google.session)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.find_by_title title
|
49
|
+
sheet = session_spreadsheets.detect do |spreadsheet|
|
50
|
+
spreadsheet.title.match(title)
|
51
|
+
end
|
52
|
+
|
53
|
+
sheet && new(sheet, session: Skypager.google.session)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.session_spreadsheets
|
57
|
+
@session_spreadsheets ||= Skypager.google.api.spreadsheets
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.create_from_data(data, options={})
|
61
|
+
require 'csv'
|
62
|
+
|
63
|
+
headers = Array(options[:headers]).map(&:to_s)
|
64
|
+
|
65
|
+
tmpfile = "tmp-csv.csv"
|
66
|
+
|
67
|
+
CSV.open(tmpfile, "wb") do |csv|
|
68
|
+
csv << headers
|
69
|
+
|
70
|
+
data.each do |row|
|
71
|
+
csv << headers.map do |header|
|
72
|
+
row = row.stringify_keys
|
73
|
+
row[header.to_s]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
spreadsheet = Skypager::Sync.google.api.upload_from_file(tmpfile, options[:title], :content_type => "text/csv")
|
79
|
+
|
80
|
+
if options[:skypager_config_info]
|
81
|
+
config_line = "data_source :#{ spreadsheet.title.to_s.downcase.underscore }, :type => 'google', :key => '#{ spreadsheet.key }'\n"
|
82
|
+
|
83
|
+
puts "Adding the following line to your config.rb: \n #{config_line}"
|
84
|
+
|
85
|
+
File.open("config.rb", "a+") do |fh|
|
86
|
+
fh.write("\n")
|
87
|
+
fh.write(config_line)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
new(spreadsheet.title, key: spreadsheet.key)
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def title
|
96
|
+
@name ||= spreadsheet.try(:title)
|
97
|
+
end
|
98
|
+
|
99
|
+
def edit_url
|
100
|
+
spreadsheet.human_url
|
101
|
+
end
|
102
|
+
|
103
|
+
def share_write_access_with *emails
|
104
|
+
acl = spreadsheet.acl
|
105
|
+
|
106
|
+
Array(emails).flatten.each do |email|
|
107
|
+
acl.push scope_type: "user",
|
108
|
+
with_key: false,
|
109
|
+
role: "writer",
|
110
|
+
scope: email
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def share_read_access_with *emails
|
115
|
+
acl = spreadsheet.acl
|
116
|
+
|
117
|
+
Array(emails).flatten.each do |email|
|
118
|
+
acl.push scope_type: "user",
|
119
|
+
with_key: false,
|
120
|
+
role: "reader",
|
121
|
+
scope: email
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_to_collection collection_title
|
126
|
+
collection = if collection_title.is_a?(GoogleDrive::Collection)
|
127
|
+
collection_title
|
128
|
+
else
|
129
|
+
session.collections.find do |c|
|
130
|
+
c.title == collection_title
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if !collection
|
135
|
+
collection_names = session.collections.map(&:title)
|
136
|
+
raise 'Could not find collection in Google drive. Maybe you mean: ' + collection_names.join(', ')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def spreadsheet_key
|
141
|
+
key
|
142
|
+
end
|
143
|
+
|
144
|
+
def stale?
|
145
|
+
(!need_to_refresh? && (age > max_age)) || fresh_on_server?
|
146
|
+
end
|
147
|
+
|
148
|
+
def fresh_on_server?
|
149
|
+
refreshed_at.to_i > 0 && (last_updated_at > refreshed_at)
|
150
|
+
end
|
151
|
+
|
152
|
+
def last_updated_at
|
153
|
+
if value = spreadsheet.document_feed_entry.css('updated').try(:text) rescue nil
|
154
|
+
DateTime.parse(value).to_i
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def fetch
|
159
|
+
self.raw = process_worksheets
|
160
|
+
end
|
161
|
+
|
162
|
+
def preprocess
|
163
|
+
single? ? raw.values.flatten : raw
|
164
|
+
end
|
165
|
+
|
166
|
+
protected
|
167
|
+
|
168
|
+
def process_worksheets
|
169
|
+
worksheets.inject(Hashie::Mash.new) do |memo, parts|
|
170
|
+
k, ws = parts
|
171
|
+
header_row = Array(ws.rows[0])
|
172
|
+
column_names = header_row.map {|cell| "#{ cell }".parameterize.underscore }
|
173
|
+
rows = ws.rows.slice(1, ws.rows.length)
|
174
|
+
|
175
|
+
row_index = 1
|
176
|
+
memo[k] = rows.map do |row|
|
177
|
+
col_index = 0
|
178
|
+
|
179
|
+
_record = column_names.inject({}) do |record, field|
|
180
|
+
record[field] = "#{ row[col_index] }".strip
|
181
|
+
record["_id"] = row_index
|
182
|
+
col_index += 1
|
183
|
+
record
|
184
|
+
end
|
185
|
+
|
186
|
+
row_index += 1
|
187
|
+
|
188
|
+
_record
|
189
|
+
end
|
190
|
+
|
191
|
+
memo
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def single?
|
196
|
+
worksheets.length == 1
|
197
|
+
end
|
198
|
+
|
199
|
+
def header_rows_for_worksheet key
|
200
|
+
if key.is_a?(Fixnum)
|
201
|
+
_worksheets[key]
|
202
|
+
else
|
203
|
+
worksheets.fetch(key)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def worksheets
|
208
|
+
@worksheets ||= _worksheets.inject(Hashie::Mash.new) do |memo,ws|
|
209
|
+
key = ws.title.strip.downcase.underscore.gsub(/\s+/,'_')
|
210
|
+
memo[key] = ws
|
211
|
+
memo
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def _worksheets
|
216
|
+
@_worksheets ||= spreadsheet.worksheets
|
217
|
+
end
|
218
|
+
|
219
|
+
def spreadsheet
|
220
|
+
@spreadsheet ||= session.spreadsheet_by_key(spreadsheet_key)
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|