paperclip-googledrive 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Ivan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # PaperclipGoogledrive
2
+ --- WORK IN PROGRESS ---
3
+
4
+ PaperclipGoogledrive is a gem that extends paperclip storage for Google Drive.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'paperclip-googledrive'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install paperclip-googledrive
19
+
20
+ ## Usage
21
+
22
+ May be available soon.
23
+
24
+ Add to class
25
+ has_attach_file method and descript name of attachemnt, set storage to google drive and set credentials and options.
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
@@ -0,0 +1,3 @@
1
+
2
+ require 'paperclip'
3
+ require 'paperclip/google_drive'
@@ -0,0 +1,2 @@
1
+ require "paperclip/storage/google_drive"
2
+ require "paperclip/google_drive/railtie" if defined?(Rails)
@@ -0,0 +1,10 @@
1
+
2
+ module Paperclip
3
+ module GoogleDrive
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks do
6
+ load "paperclip/google_drive/tasks.rake"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,50 @@
1
+
2
+ require 'google/api_client'
3
+
4
+ module Paperclip
5
+ module GoogleDrive
6
+ module Rake
7
+ extend self
8
+
9
+ def authorize
10
+ puts 'Enter client ID:'
11
+ client_id = $stdin.gets.chomp
12
+ puts 'Enter client SECRET:'
13
+ client_secret = $stdin.gets.chomp.strip
14
+ puts 'Enter SCOPE:'
15
+ oauth_scope = $stdin.gets.chomp.strip
16
+ puts 'Enter redirect URI:'
17
+ redirect_uri = $stdin.gets.chomp.strip
18
+
19
+ # Create a new API client & load the Google Drive API
20
+ client = Google::APIClient.new
21
+ drive = client.discovered_api('drive', 'v2')
22
+
23
+ client.authorization.client_id = client_id
24
+ client.authorization.client_secret = client_secret
25
+ client.authorization.scope = oauth_scope
26
+ client.authorization.redirect_uri = redirect_uri
27
+
28
+ # Request authorization
29
+ uri = client.authorization.authorization_uri.to_s
30
+ puts "\nGo to this url:"
31
+ puts client.authorization.authorization_uri.to_s
32
+ puts "\n Accept the authorization request from Google in your browser"
33
+
34
+ puts "\n\n\n Google will redirect you to localhost, but just copy the code parameter out of the URL they redirect you to, paste it here and hit enter:\n"
35
+
36
+ code = $stdin.gets.chomp.strip
37
+ client.authorization.code = code
38
+ client.authorization.fetch_access_token!
39
+
40
+ puts "\nAuthorization complete!:\n\n"
41
+ puts "client = Google::APIClient.new"
42
+ puts "client.authorization.client_id = '#{client_id}'"
43
+ puts "client.authorization.client_secret = '#{client_secret}'"
44
+ puts "client.authorization.access_token = '#{client.authorization.access_token}'"
45
+ puts "client.authorization.refresh_token = '#{client.authorization.refresh_token}'"
46
+ puts "\n"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,10 @@
1
+
2
+ require "paperclip/google_drive/rake"
3
+
4
+ namespace :google_drive do
5
+ desc "Authorize Google Drive account: "
6
+ task :authorize do
7
+ Paperclip::GoogleDrive::Rake.authorize
8
+ end
9
+ end
10
+
@@ -0,0 +1,254 @@
1
+
2
+ require 'active_support/core_ext/hash/keys'
3
+ require 'active_support/inflector/methods'
4
+ require 'active_support/core_ext/object/blank'
5
+ require 'yaml'
6
+ require 'erb'
7
+ require 'google/api_client'
8
+
9
+ module Paperclip
10
+
11
+ module Storage
12
+ # * self.extended(base) add instance variable to attachment on call
13
+ # * url return url to show on site with style options
14
+ # * path(style) return title that used to insert file to store or find it in store
15
+ # * public_url_for title return url to file if find by title or url to default image if set
16
+ # * search_for_title(title) take title, search in given folder and if it finds a file, return id of a file or nil
17
+ # * metadata_by_id(file_i get file metadata from store, used to back url or find out value of trashed
18
+ # * exists?(style) check either exists file with title or not
19
+ # * default_image return url to default url if set in option
20
+ # * find_public_folder return id of Public folder, must be in options
21
+ # return id of Public folder, must be in options
22
+ # * file_tit return base pattern of title or custom one set by user
23
+ # * parse_credentials(credenti get credentials from file, hash or path
24
+ # * assert_required_keys check either all ccredentials keys is set
25
+ # * original_extension return extension of file
26
+
27
+ module GoogleDrive
28
+
29
+ def self.extended(base)
30
+ begin
31
+ require 'google-api-client'
32
+ rescue LoadError => e
33
+ e.message << " (You may need to install the google-api-client gem)"
34
+ raise e
35
+ end unless defined?(Google)
36
+
37
+ base.instance_eval do
38
+ @google_drive_credentials = parse_credentials(@options[:google_drive_credentials] || {})
39
+ @google_drive_options = @options[:google_drive_options] || {}
40
+ google_api_client # Force validations of credentials
41
+ end
42
+ end
43
+ #
44
+ def flush_writes
45
+ @queued_for_write.each do |style, file|
46
+ if exists?(path(style))
47
+ raise FileExists, "file \"#{path(style)}\" already exists in your Google Drive"
48
+ else
49
+ #upload(style, file) #style file
50
+ client = google_api_client
51
+ drive = client.discovered_api('drive', 'v2')
52
+ oauth2 = client.discovered_api('oauth2', 'v2')
53
+ result = client.execute!(:api_method => oauth2.userinfo.get)
54
+ client.authorization.access_token = result.request.authorization.access_token
55
+ client.authorization.refresh_token = result.request.authorization.refresh_token
56
+ title, mime_type = title_for_file(style), "#{content_type}"
57
+ parent_id = @google_drive_options[:public_folder_id] # folder_id for Public folder
58
+ metadata = drive.files.insert.request_schema.new({
59
+ 'title' => title, #if it is no extension, that is a folder and another folder
60
+ 'description' => 'paperclip file on google drive',
61
+ 'mimeType' => mime_type })
62
+ if parent_id
63
+ metadata.parents = [{'id' => parent_id}]
64
+ end
65
+ media = Google::APIClient::UploadIO.new( file, mime_type)
66
+ result = client.execute(
67
+ :api_method => drive.files.insert,
68
+ :body_object => metadata,
69
+ :media => media,
70
+ :parameters => {
71
+ 'uploadType' => 'multipart',
72
+ 'alt' => 'json' })
73
+ end
74
+ end
75
+ after_flush_writes
76
+ @queued_for_write = {}
77
+ end
78
+ #
79
+ def flush_deletes
80
+ @queued_for_delete.each do |path|
81
+ Paperclip.log("delete #{path}")
82
+ client = google_api_client
83
+ drive = client.discovered_api('drive', 'v2')
84
+ file_id = search_for_title(path)
85
+ unless file_id.nil?
86
+ folder_id = find_public_folder
87
+ parameters = {'fileId' => file_id,
88
+ 'folder_id' => folder_id }
89
+ result = client.execute(
90
+ :api_method => drive.files.delete,
91
+ :parameters => parameters)
92
+ if result.status != 200
93
+ puts "An error occurred: #{result.data['error']['message']}"
94
+ end
95
+ end
96
+ end
97
+ @queued_for_delete = []
98
+ end
99
+ #
100
+ def google_api_client
101
+ @google_api_client ||= begin
102
+ assert_required_keys
103
+ # Initialize the client & Google+ API
104
+ client = Google::APIClient.new
105
+ client.authorization.client_id = @google_drive_credentials[:client_id]
106
+ client.authorization.client_secret = @google_drive_credentials[:client_secret]
107
+ client.authorization.access_token = @google_drive_credentials[:access_token]
108
+ client.authorization.refresh_token = @google_drive_credentials[:refresh_token]
109
+ client
110
+ end
111
+ end
112
+ #
113
+ def google_drive
114
+ client = google_api_client
115
+ drive = client.discovered_api('drive', 'v2')
116
+ drive
117
+ end
118
+
119
+ def url(*args)
120
+ if present?
121
+ style = args.first.is_a?(Symbol) ? args.first : default_style
122
+ options = args.last.is_a?(Hash) ? args.last : {}
123
+ public_url_for(path(style))
124
+ else
125
+ default_image
126
+ end
127
+ end
128
+
129
+ def path(style)
130
+ title_for_file(style)
131
+ end
132
+
133
+ def title_for_file(style)
134
+ file_name = instance.instance_exec(style, &file_title)
135
+
136
+ style_suffix = (style != default_style ? "_#{style}" : "")
137
+
138
+ if original_extension.present? && file_name =~ /#{original_extension}$/
139
+ file_name.sub(original_extension, "#{style_suffix}#{original_extension}")
140
+ else
141
+ file_name + style_suffix + original_extension.to_s
142
+ end
143
+ end # full title
144
+
145
+ def public_url_for title
146
+ searched_id = search_for_title(title) #return id if any or style
147
+ if searched_id.nil? # it finds some file
148
+ default_image
149
+ else
150
+ metadata = metadata_by_id(searched_id)
151
+ metadata['webContentLink']
152
+ end
153
+ end # url
154
+ # take title, search in given folder and if it finds a file, return id of a file or nil
155
+ def search_for_title(title)
156
+ parameters = {
157
+ 'folderId' => find_public_folder,
158
+ 'q' => "title contains '#{title}'", # full_title
159
+ 'fields' => 'items/id'}
160
+ client = google_api_client
161
+ drive = client.discovered_api('drive', 'v2')
162
+ result = client.execute(:api_method => drive.children.list,
163
+ :parameters => parameters)
164
+ if result.status == 200
165
+ if result.data.items.length > 0
166
+ result.data.items[0]['id']
167
+ elsif result.data.items.length == 0
168
+ nil
169
+ else
170
+ nil
171
+ end
172
+ end
173
+ end # id or nil
174
+
175
+ def metadata_by_id(file_id)
176
+ if file_id.is_a? String
177
+ client = google_api_client
178
+ drive = client.discovered_api('drive', 'v2')
179
+ result = client.execute(
180
+ :api_method => drive.files.get,
181
+ :parameters => {'fileId' => file_id,
182
+ 'fields' => 'title, id, webContentLink, labels/trashed' })
183
+ if result.status == 200
184
+ result.data # data.class # => Hash
185
+ end
186
+ end
187
+ end
188
+
189
+ def exists?(style)
190
+ result_id = search_for_title(path(style))
191
+ if result_id.nil?
192
+ false
193
+ else
194
+ data_hash = metadata_by_id(result_id)
195
+ !data_hash['labels']['trashed'] # if trashed -> not exists
196
+ end
197
+ end
198
+
199
+ def default_image
200
+ if @google_drive_options[:default_url] #if default image is set
201
+ title = @google_drive_options[:default_url]
202
+ searched_id = search_for_title(title) # id
203
+ metadata = metadata_by_id(searched_id) unless searched_id.nil?
204
+ metadata['webContentLink']
205
+ else
206
+ 'No picture' # ---- ?
207
+ end
208
+ end
209
+
210
+ def find_public_folder
211
+ unless @google_drive_options[:public_folder_id]
212
+ raise KeyError, "you must set a Public folder if into options"
213
+ end
214
+ @google_drive_options[:public_folder_id]
215
+ end
216
+ class FileExists < ArgumentError
217
+ end
218
+ private
219
+
220
+ def file_title
221
+ return @google_drive_options[:path] if @google_drive_options[:path] #path: proc
222
+ eval %(proc { |style| "\#{id}_\#{#{name}.original_filename}"})
223
+ end
224
+
225
+ def parse_credentials(credentials)
226
+ result =
227
+ case credentials
228
+ when File
229
+ YAML.load(ERB.new(File.read(credentials.path)).result)
230
+ when String, Pathname
231
+ YAML.load(ERB.new(File.read(credentials)).result)
232
+ when Hash
233
+ credentials
234
+ else
235
+ raise ArgumentError, ":google_drive_credentials are not a path, file, nor a hash"
236
+ end
237
+ result.symbolize_keys #or string keys
238
+ end
239
+ # check either all ccredentials keys is set
240
+ def assert_required_keys
241
+ keys_list = [:client_id, :client_secret, :access_token, :refresh_token]
242
+ keys_list.each do |key|
243
+ @google_drive_credentials.fetch(key)
244
+ end
245
+ end
246
+ # return extension of file
247
+ def original_extension
248
+ File.extname(original_filename)
249
+ end
250
+ end
251
+
252
+ end
253
+
254
+ end
@@ -0,0 +1,3 @@
1
+ module PaperclipGoogleDrive
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #require File.expand_path('../lib/paperclip_googledrive/version', __FILE__)
3
+ $:.push File.expand_path("../lib", __FILE__)
4
+ require "paperclip/version"
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "paperclip-googledrive"
8
+ gem.version = PaperclipGoogleDrive::VERSION
9
+ gem.authors = ['evinsou']
10
+ gem.email = ["evinsou@gmail.com"]
11
+
12
+ gem.summary = %q{Extends Paperclip with Google Drive storage}
13
+ gem.description = %q{paperclip-googledrive extends paperclip support of storage for google drive storage}
14
+ gem.homepage = ""
15
+
16
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ gem.files = Dir["lib/**/*"] + ["README.md", "LICENSE", "paperclip-googledrive.gemspec"]
18
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+
20
+ gem.require_paths = ["lib"]
21
+ gem.required_ruby_version = ">= 1.9.2"
22
+ gem.license = "MIT"
23
+
24
+ gem.add_dependency "paperclip", "~> 3.4"
25
+ gem.add_dependency 'google-api-client', "~> 0.5"
26
+
27
+ gem.add_development_dependency "rake", ">= 0.9"
28
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paperclip-googledrive
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - evinsou
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: paperclip
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.4'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.4'
30
+ - !ruby/object:Gem::Dependency
31
+ name: google-api-client
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '0.5'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '0.5'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0.9'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ description: paperclip-googledrive extends paperclip support of storage for google
63
+ drive storage
64
+ email:
65
+ - evinsou@gmail.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - lib/paperclip-googledrive.rb
71
+ - lib/paperclip/google_drive.rb
72
+ - lib/paperclip/storage/google_drive.rb
73
+ - lib/paperclip/version.rb
74
+ - lib/paperclip/google_drive/railtie.rb
75
+ - lib/paperclip/google_drive/rake.rb
76
+ - lib/paperclip/google_drive/tasks.rake
77
+ - README.md
78
+ - LICENSE
79
+ - paperclip-googledrive.gemspec
80
+ homepage: ''
81
+ licenses:
82
+ - MIT
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: 1.9.2
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.24
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Extends Paperclip with Google Drive storage
105
+ test_files: []