paperclip-storage-aliyun 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NDE1YjU0M2RkOGFkNGJmODBkYTAwOGRhNzIwYmFmNjk1MTQwMzg1Yg==
5
- data.tar.gz: !binary |-
6
- ZGZkN2MzZDM4OTI2MjdkMjFjNzY2NDQ0MDE0OGY0YTk4YjZiODJkOA==
2
+ SHA1:
3
+ metadata.gz: 770e2aba77af7013237abcb823fec49c244d15d3
4
+ data.tar.gz: 199af51f6159ab6b0138eab907b7dd7286b2fd2a
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- N2NjZjUzZGZlYjQxNTU0YzEyZTJmMzZlNGY4YmZhMTlkMzMxY2NjNDY5NzIy
10
- NDIyZTA5ZDFhMmQ0YWQzNmZlNGUxNDEwMzU1NDhmOGUyZjM1NDhiMjJhNTgw
11
- OGRhOWU5MWI5Mjk4MTZjZDNjNmNhMGNkNzdiNjM3ODI3NTM2NDI=
12
- data.tar.gz: !binary |-
13
- ZGFiNmFmNTQ2MjNiMDMxZjExZWU2NmU4ZWQxMzdjYTY5ZDQ1NWZlZDFjYmEz
14
- MjNmOWM1NTBmNzViOGRmY2I1ZmY0MjY5NmJmMzYwYjJmMTI4YzEyZDhjYmU5
15
- MmFiZGQzMGZkMTVlNjEyMjA3ZWM4NjM4YWJjMTAyZDQxN2E0OWU=
6
+ metadata.gz: 418741aa19eeb9400e7cae5eb9448c671a99688632cb19a9e7c6c8c43a269297c608c2ef53dc84881ff437833ecdaa826db8f7ece5c0052ac453aa61a9703422
7
+ data.tar.gz: 27af1cb2c3f924a9f1d736206a57c648d82a3b10b03c3e1ed373dcc8c9d48050f19344c1d7bd22aafe8a021919284c71dbb8fb53170d35142d8a0fddaec3059f
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ .yardoc/
3
+ doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'http://ruby.taobao.org'
2
+
3
+ # A database backend that translates database interactions into no-ops. Using
4
+ # NullDB enables you to test your model business logic - including after_save
5
+ # hooks - without ever touching a real database.
6
+ gem "activerecord-nulldb-adapter"
7
+
8
+ gemspec
9
+
10
+ group :test do
11
+ gem 'activerecord', '~> 4.0.0'
12
+ gem 'rspec', '~> 3.3.0'
13
+ gem 'pry'
14
+ gem 'pry-nav'
15
+ end
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ Aliyun Open Storage Service for Paperclip
2
+ ===
3
+ This gem implement the support for [Aliyun open storage service(OSS)](http://oss.aliyun.com) to [Paperclip](https://github.com/thoughtbot/paperclip).
4
+
5
+ #### Installation
6
+ ```shell
7
+ gem install paperclip-storage-aliyun
8
+ ```
9
+ Or, if you are using a bundler, you can append the following line into your **Gemfile**:
10
+ ```ruby
11
+ gem 'paperclip-storage-aliyun'
12
+ ```
13
+
14
+ #### Configuration
15
+ In order to make all the things work, you should do some important configurations through a initializer:
16
+
17
+ If you are developing a Rails application, you can append a new initializer like:
18
+ ```ruby
19
+ # [rails_root]/config/initializers/paperclip-aliyun-configuration.rb
20
+ Paperclip::Attachment.default_options[:aliyun] = {
21
+ access_id: '3VL9XMho8iCushj8',
22
+ access_key: 'VAUI2q7Tc6yTh1jr3kBsEUzZ84gEa2',
23
+ bucket: 'xx-test',
24
+ data_centre: 'hangzhou',
25
+ internal: false
26
+ }
27
+ ```
28
+ Then, in the model which defines the attachment, specify your storage and other options, for example:
29
+ ```ruby
30
+ # [rails_root]/app/models/image.rb
31
+ include Paperclip::Storage::Aliyun
32
+
33
+ class Image < ActiveRecord::Base
34
+ has_attached_file :attachment, {
35
+ storage: :aliyun,
36
+ styles: { thumbnail: "60x60#"},
37
+ path: 'public/system/:class/:attachment/:id_partition/:style/:filename',
38
+ url: "http://#{oss_connection.fetch_file_host}/public/system/:class/:attachment/:id_partition/:style/:filename"
39
+ }
40
+ end
41
+ ```
42
+
43
+ ### Thanks
44
+ 这个gem是在参考[Jason Lee](https://github.com/huacnlee)先生写的gem [carrierwave-aliyun](https://github.com/huacnlee/carrierwave-aliyun)的基础上写出来的,其中主要直接用了阿里云接口的代码以及对应的测试代码,在此基础上自行实现Paperclip必要的`get`方法以及`exists?`方法。在此特别感谢**Jason Lee**先生的开源代码。
@@ -0,0 +1,203 @@
1
+ # encoding: utf-8
2
+
3
+ require 'openssl'
4
+ require 'digest/md5'
5
+ require "rest-client"
6
+ require "base64"
7
+ require 'uri'
8
+ require 'aliyun/data_center'
9
+
10
+ module Aliyun
11
+ class Connection
12
+ include DataCenter
13
+ # Initialize the OSS connection
14
+ #
15
+ # @param [Hash] An options to specify connection details
16
+ # @option access_id [String] used to set "Authorization" request header
17
+ # @option access_key [String] the access key
18
+ # @option bucket [String] bucket used to access
19
+ # @option data_center [String] available data center name, e.g. 'hangzhou'
20
+ # @option internal [true, false] if the service should be accessed through internal network
21
+ # @option host [String] force the host to a given value, only use it when this gem can not work expectly
22
+ # @note both access_id and acces_key are related to authorization algorithm:
23
+ # https://docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-header
24
+ def initialize(options = {})
25
+ @aliyun_access_id = options[:access_id]
26
+ @aliyun_access_key = options[:access_key]
27
+ @aliyun_bucket = options[:bucket]
28
+
29
+ @endpoint = get_endpoint(options)
30
+
31
+ @aliyun_upload_host = "#{@aliyun_bucket}.#{@endpoint}"
32
+
33
+ @aliyun_host = options[:host] || @aliyun_upload_host
34
+ end
35
+
36
+ # the file host according to the connection configurations
37
+ #
38
+ # @return [String] the host value
39
+ def fetch_file_host
40
+ @aliyun_host
41
+ end
42
+
43
+ # Return the meta informations for the a file specified by the path
44
+ # https://docs.aliyun.com/#/pub/oss/api-reference/object&HeadObject
45
+ #
46
+ # @param path [String] the path of file storaged in Aliyun OSS
47
+ # @return [Hash] the meta data of the file
48
+ # @note the example headers will be like:
49
+ #
50
+ # {
51
+ # {:date=>"Sun, 02 Aug 2015 02:42:45 GMT",
52
+ # :content_type=>"image/jpg",
53
+ # :content_length=>"125198",
54
+ # :connection=>"close",
55
+ # :accept_ranges=>"bytes",
56
+ # :etag=>"\"336262A42E5B99AFF5B8BC66611FC156\"",
57
+ # :last_modified=>"Sun, 01 Dec 2013 16:39:57 GMT",
58
+ # :server=>"AliyunOSS",
59
+ # :x_oss_object_type=>"Normal",
60
+ # :x_oss_request_id=>"55BD83A5D4C05BDFF4A329E0"}}
61
+ #
62
+ def head(path)
63
+ url = path_to_url(path)
64
+ RestClient.head(url).headers
65
+ rescue RestClient::ResourceNotFound
66
+ {}
67
+ end
68
+
69
+ # Upload File to Aliyun OSS
70
+ # https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject
71
+ #
72
+ # @param path [String] the target storing path on the oss
73
+ # @param file [File] an instance of File represents a file to be uploaded
74
+ # @param options [Hash]
75
+ # - content_type - MimeType value for the file, default is "image/jpg"
76
+ #
77
+ # @return [String] The downloadable url of the uploaded file
78
+ # @return [nil] if the uploading failed
79
+ def put(path, file, options={})
80
+ path = format_path(path)
81
+ bucket_path = get_bucket_path(path)
82
+ content_md5 = Digest::MD5.file(file)
83
+ content_type = options[:content_type] || "image/jpg"
84
+ date = gmtdate
85
+ url = path_to_url(path)
86
+ auth_sign = sign("PUT", bucket_path, content_md5, content_type, date)
87
+ headers = {
88
+ "Authorization" => auth_sign,
89
+ "Content-Type" => content_type,
90
+ "Content-Length" => file.size,
91
+ "Date" => date,
92
+ "Host" => @aliyun_upload_host,
93
+ "Expect" => "100-Continue"
94
+ }
95
+ response = RestClient.put(URI.encode(url), file, headers)
96
+ response.code == 200 ? path_to_url(path) : nil
97
+ end
98
+
99
+ # Delete a file from the OSS
100
+ # https://docs.aliyun.com/#/pub/oss/api-reference/object&DeleteObject
101
+ #
102
+ # @param path [String] the path to retrieve the file on remote storage
103
+ # @return [String] the expired url to the file, if the file deleted successfully
104
+ # @return [nil] if the delete operation failed
105
+ def delete(path)
106
+ path = format_path(path)
107
+ bucket_path = get_bucket_path(path)
108
+ date = gmtdate
109
+ headers = {
110
+ "Host" => @aliyun_upload_host,
111
+ "Date" => date,
112
+ "Authorization" => sign("DELETE", bucket_path, "", "" ,date)
113
+ }
114
+ url = path_to_url(path)
115
+ response = RestClient.delete(URI.encode(url), headers)
116
+ response.code == 204 ? url : nil
117
+ end
118
+
119
+ # Download the file from OSS
120
+ # https://docs.aliyun.com/#/pub/oss/api-reference/object&GetObject
121
+ #
122
+ # @param path [String] the path to retrieve the file on remote storage
123
+ # @return [?] the file content consist of bytes
124
+ def get(path)
125
+ path = format_path(path)
126
+ bucket_path = get_bucket_path(path)
127
+ date = gmtdate
128
+ headers = {
129
+ "Host" => @aliyun_upload_host,
130
+ "Date" => date,
131
+ "Authorization" => sign("GET", bucket_path, "", "" ,date)
132
+ }
133
+ url = path_to_url(path)
134
+ response = RestClient.get(URI.encode(url), headers)
135
+ response.body
136
+ end
137
+
138
+ # Determine if the file exists on the OSS
139
+ # https://docs.aliyun.com/#/pub/oss/api-reference/object&HeadObject
140
+ #
141
+ # @param path [String] the path to retrieve the file on remote storage
142
+ # @return [true] if file exists
143
+ # @return [false] if file could not be found
144
+ def exists?(path)
145
+ head(path).empty? ? false : true
146
+ end
147
+
148
+ # The GMT format time referenced from HTTP 1.1
149
+ # https://docs.aliyun.com/#/pub/oss/api-reference/public-header
150
+ #
151
+ # @return [String] a string represents the formated time, e.g. "Wed, 05 Sep. 2012 23:00:00 GMT"
152
+ def gmtdate
153
+ Time.now.gmtime.strftime("%a, %d %b %Y %H:%M:%S GMT")
154
+ end
155
+
156
+ # remove leading slashes in the path
157
+ #
158
+ # @param path [String] the path to retrieve the file on remote storage
159
+ # @return [String] the new string after removing leading slashed
160
+ def format_path(path)
161
+ return "" if path.blank?
162
+ path.gsub!(/^\/+/,"")
163
+
164
+ path
165
+ end
166
+
167
+ # A path consis of the bucket name and file name
168
+ # https://docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-header
169
+ #
170
+ # @param path [String] the path to retrieve the file on remote storage
171
+ # @return [String] the expected bucket path, e.g. "test-bucket/oss-api.pdf"
172
+ def get_bucket_path(path)
173
+ [@aliyun_bucket,path].join("/")
174
+ end
175
+
176
+ # The full path contains host name to the file
177
+ #
178
+ # @param path [String] the path to retrieve the file on remote storage
179
+ # @return [String] the expected full path, e.g. "http://martin-test.oss-cn-hangzhou.aliyuncs.com/oss-api.pdf"
180
+ def path_to_url(path)
181
+ return path if path =~ /^https?:\/{2}/ # 已经是全路径
182
+ "http://#{fetch_file_host}/#{path}"
183
+ end
184
+
185
+ private
186
+ # The signature algorithm
187
+ # https://docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-header
188
+ #
189
+ # @param verb [String] the request verb, e.g. "GET" or "DELETE"
190
+ # @param content_md5 [String] the md5 value for the content to be uploaded
191
+ # @param content_type [String] the content type of the file, e.g. "application/pdf"
192
+ # @param date [String] the GMT formatted date string
193
+ def sign(verb, path, content_md5 = '', content_type = '', date)
194
+ canonicalized_oss_headers = ''
195
+ canonicalized_resource = "/#{path}"
196
+ string_to_sign = "#{verb}\n\n#{content_type}\n#{date}\n#{canonicalized_oss_headers}#{canonicalized_resource}"
197
+ digest = OpenSSL::Digest.new('sha1')
198
+ h = OpenSSL::HMAC.digest(digest, @aliyun_access_key, string_to_sign)
199
+ h = Base64.encode64(h)
200
+ "OSS #{@aliyun_access_id}:#{h}"
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,20 @@
1
+ require 'aliyun/errors'
2
+
3
+ module Aliyun
4
+ module DataCenter
5
+ # https://docs.aliyun.com/#/pub/oss/product-documentation/domain-region
6
+ AVAILABLE_CHINA_DATA_CENTERS = %w(hangzhou qingdao beijing hongkong shenzhen shanghai)
7
+ AVAILABLE_US_DATA_CENTERS = %w(us-west-1)
8
+
9
+ def get_endpoint(options)
10
+ data_center = options[:data_center]
11
+ if (AVAILABLE_CHINA_DATA_CENTERS + AVAILABLE_US_DATA_CENTERS).exclude?(data_center)
12
+ raise InvalildDataCenter, "Unsupported Data Center #{data_center} Detected"
13
+ end
14
+
15
+ internal = options[:internal] ? "-internal" : ''
16
+ country = AVAILABLE_CHINA_DATA_CENTERS.include?(data_center) ? 'cn' : 'us'
17
+ "oss-#{country}-#{data_center}#{internal}.aliyuncs.com"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ module Aliyun
2
+ class InvalildDataCenter < StandardError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'paperclip'
2
+
3
+ require 'paperclip/storage/aliyun'
4
+ require 'aliyun/connection'
@@ -0,0 +1,46 @@
1
+ module Paperclip
2
+ module Storage
3
+ module Aliyun
4
+ def self.extended(base)
5
+ end
6
+
7
+ def exists?(style = default_style)
8
+ return false unless path(style)
9
+
10
+ oss_connection.exists? path(style)
11
+ end
12
+
13
+ def flush_writes #:nodoc:
14
+ @queued_for_write.each do |style_name, file|
15
+ oss_connection.put path(style_name), (File.new file.path), content_type: file.content_type
16
+ end
17
+
18
+ after_flush_writes
19
+
20
+ @queued_for_write = {}
21
+ end
22
+
23
+ def flush_deletes #:nodoc:
24
+ @queued_for_delete.each do |path|
25
+ oss_connection.delete path
26
+ end
27
+
28
+ @queued_for_delete = []
29
+ end
30
+
31
+ def copy_to_local_file(style = default_style, local_dest_path)
32
+ log("copying #{path(style)} to local file #{local_dest_path}")
33
+ local_file = ::File.open(local_dest_path, 'wb')
34
+ remote_file_str = oss_connection.get path(style)
35
+ local_file.write(remote_file_str)
36
+ local_file.close
37
+ end
38
+
39
+ def oss_connection
40
+ return @oss_connection if @oss_connection
41
+
42
+ @oss_connection ||= ::Aliyun::Connection.new Paperclip::Attachment.default_options[:aliyun]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'paperclip-storage-aliyun'
3
+ s.platform = Gem::Platform::RUBY
4
+ s.require_path = 'lib'
5
+ s.summary = 'Extend a Aliyun OSS storage for paperclip'
6
+ s.description = 'Extend a Aliyun OSS storage for paperclip'
7
+ s.version = '0.0.3'
8
+ s.files = `git ls-files`.split("\n")
9
+ s.authors = ['Martin Hong']
10
+ s.email = 'hongzeqin@gmail.com'
11
+ s.homepage = 'https://github.com/Martin91/paperclip-storage-aliyun'
12
+ s.license = 'MIT'
13
+
14
+ s.add_runtime_dependency 'paperclip', '>= 3.5.2'
15
+ s.add_runtime_dependency 'rest-client', '>= 1.6.7'
16
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ require "net/http"
4
+
5
+ describe Aliyun::Connection do
6
+ before :all do
7
+ @connection = ::Aliyun::Connection.new OSS_CONNECTION_OPTIONS
8
+ @path = 'a/a.jpg'
9
+ end
10
+
11
+ describe '#initialize' do
12
+ it "raise error when use invalid data center" do
13
+ expect do
14
+ ::Aliyun::Connection.new data_center: 'guangzhou'
15
+ end.to raise_error(Aliyun::InvalildDataCenter)
16
+ end
17
+ end
18
+
19
+ describe '#put' do
20
+ it "upload the attachment" do
21
+ url = @connection.put @path, load_attachment("girl.jpg")
22
+ response_code = Net::HTTP.get_response(URI.parse(url)).code
23
+ expect(response_code).to eq("200")
24
+ end
25
+
26
+ it "support setting content type" do
27
+ content_type = "application/pdf"
28
+ path = 'pdfs/masu.pdf'
29
+ @connection.put path, load_attachment("masu.pdf"), content_type: content_type
30
+ file_meta = @connection.head(path)
31
+ expect(file_meta[:content_type]).to eq(content_type)
32
+
33
+ @connection.delete path
34
+ end
35
+ end
36
+
37
+ describe '#delete' do
38
+ it "delete the attachment" do
39
+ url = @connection.delete @path
40
+ response_code = Net::HTTP.get_response(URI.parse(url)).code
41
+ expect(response_code).to eq("404")
42
+ end
43
+ end
44
+
45
+ describe "#exists?" do
46
+ before :all do
47
+ @connection.put @path, load_attachment("girl.jpg")
48
+ end
49
+
50
+ it "return true if the file has been uploaded" do
51
+ expect(@connection.exists?(@path)).to be_truthy
52
+ end
53
+
54
+ it "return false if the specified file didn't exist" do
55
+ @connection.delete @path
56
+ expect(@connection.exists?(@path)).to be_falsey
57
+ end
58
+ end
59
+ end
Binary file
Binary file
@@ -0,0 +1,8 @@
1
+ require "active_record"
2
+ require "paperclip"
3
+
4
+ ActiveRecord::Schema.define do
5
+ create_table :posts, force: true do |t|
6
+ t.attachment :attachment
7
+ end
8
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require "open-uri"
3
+ require 'net/http'
4
+ require 'support/post'
5
+
6
+ describe Paperclip::Storage::Aliyun do
7
+ before :all do
8
+ @file = load_attachment('girl.jpg')
9
+ @post = Post.create attachment: @file
10
+ end
11
+
12
+ after :all do
13
+ if @post && @post.respond_to?(:id)
14
+ @post.destroy!
15
+ end
16
+
17
+ @file.close
18
+ end
19
+
20
+ describe "#flush_writes" do
21
+ it "uploads the attachment to Aliyun" do
22
+ response = open(@post.attachment.url)
23
+ expect(response).to be_truthy
24
+ end
25
+
26
+ it "get uploaded file from Aliyun" do
27
+ attachment = open @post.attachment.url
28
+ expect(attachment.size).to eq(@file.size)
29
+ end
30
+
31
+ it "set content type according to the original file" do
32
+ attachment = load_attachment('masu.pdf')
33
+ post = Post.create attachment: attachment
34
+ headers = RestClient.head(post.attachment.url).headers
35
+ expect(headers[:content_type]).to eq('application/pdf')
36
+
37
+ post.destroy
38
+ end
39
+ end
40
+
41
+ describe "#exists?" do
42
+ it "returns true if the file exists on Aliyun" do
43
+ expect(@post.attachment).to exist
44
+ end
45
+
46
+ it "returns false if the file doesn't exist on Aliyun" do
47
+ post = Post.new attachment: @file
48
+ expect(post.attachment).not_to exist
49
+ end
50
+
51
+ it "not raise exception when attachment not saved" do
52
+ post = Post.create
53
+ expect{post.attachment.exists?}.not_to raise_error
54
+ end
55
+ end
56
+
57
+ describe "#copy_to_local_file" do
58
+ it "copies file from Aliyun to a local file" do
59
+ destination = File.join(Bundler.root, "tmp/photo.jpg")
60
+ @post.attachment.copy_to_local_file(:original, destination)
61
+ expect(File.exists?(destination)).to be_truthy
62
+
63
+ File.delete destination
64
+ end
65
+ end
66
+
67
+ describe "#flush_deletes" do
68
+ it "deletes the attachment from Aliyun" do
69
+ attachment_url = @post.attachment.url
70
+ @post.destroy
71
+
72
+ response_code = Net::HTTP.get_response(URI.parse(attachment_url)).code
73
+ expect(response_code).to eq("404")
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,29 @@
1
+ require 'pry'
2
+ require 'pry-nav'
3
+ require 'paperclip-storage-aliyun'
4
+
5
+ Dir[File.join(Bundler.root, "spec/support/**/*.rb")].each &method(:require)
6
+
7
+ include Paperclip::Storage::Aliyun
8
+ def file_host
9
+ oss_connection.fetch_file_host
10
+ end
11
+
12
+ OSS_CONNECTION_OPTIONS = {
13
+ access_id: '3VL9XMho8iCuslj8',
14
+ access_key: 'VAUI2q7Tc6yTf1jr3kBsEUzZ84gEa2',
15
+ bucket: 'martin-test',
16
+ data_center: 'hangzhou',
17
+ internal: false
18
+ # host: nil
19
+ }
20
+
21
+ # paperclip初始化设置
22
+ Paperclip::Attachment.default_options[:storage] = :aliyun
23
+ Paperclip::Attachment.default_options[:path] = 'public/system/:class/:attachment/:id_partition/:style/:filename'
24
+ Paperclip::Attachment.default_options[:aliyun] = OSS_CONNECTION_OPTIONS
25
+ Paperclip::Attachment.default_options[:url] = "http://#{file_host}/public/system/:class/:attachment/:id_partition/:style/:filename"
26
+
27
+ def load_attachment(file_name)
28
+ File.open (File.expand_path "attachments/#{file_name}", File.dirname(__FILE__)), 'rb'
29
+ end
@@ -0,0 +1,24 @@
1
+ require "active_record"
2
+ require "nulldb"
3
+ require "paperclip"
4
+
5
+ class Post < ActiveRecord::Base
6
+ include Paperclip::Glue
7
+
8
+ has_attached_file :attachment
9
+ do_not_validate_attachment_file_type :attachment
10
+ end
11
+
12
+ RSpec.configure do |config|
13
+ config.before(:all) do
14
+ FileUtils.mkdir_p File.join(Bundler.root, "tmp")
15
+ ActiveRecord::Base.establish_connection(
16
+ adapter: "nulldb",
17
+ schema: File.join(Bundler.root, "spec/fixtures/schema.rb"),
18
+ )
19
+ end
20
+
21
+ config.after(:all) do
22
+ ActiveRecord::Base.remove_connection
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ require "paperclip"
2
+
3
+ module Paperclip
4
+ module Interpolations
5
+ module Rails
6
+ def self.root
7
+ end
8
+ end
9
+ end
10
+ end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paperclip-storage-aliyun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Hong
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-01 00:00:00.000000000 Z
11
+ date: 2015-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: paperclip
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.5.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.5.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rest-client
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.6.7
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.6.7
41
41
  description: Extend a Aliyun OSS storage for paperclip
@@ -43,7 +43,25 @@ email: hongzeqin@gmail.com
43
43
  executables: []
44
44
  extensions: []
45
45
  extra_rdoc_files: []
46
- files: []
46
+ files:
47
+ - ".gitignore"
48
+ - ".rspec"
49
+ - Gemfile
50
+ - README.md
51
+ - lib/aliyun/connection.rb
52
+ - lib/aliyun/data_center.rb
53
+ - lib/aliyun/errors.rb
54
+ - lib/paperclip-storage-aliyun.rb
55
+ - lib/paperclip/storage/aliyun.rb
56
+ - paperclip-storage-aliyun.gemspec
57
+ - spec/aliyun_spec.rb
58
+ - spec/attachments/girl.jpg
59
+ - spec/attachments/masu.pdf
60
+ - spec/fixtures/schema.rb
61
+ - spec/lib/paperclip/storage/aliyun_spec.rb
62
+ - spec/spec_helper.rb
63
+ - spec/support/post.rb
64
+ - spec/support/rails.rb
47
65
  homepage: https://github.com/Martin91/paperclip-storage-aliyun
48
66
  licenses:
49
67
  - MIT
@@ -54,18 +72,19 @@ require_paths:
54
72
  - lib
55
73
  required_ruby_version: !ruby/object:Gem::Requirement
56
74
  requirements:
57
- - - ! '>='
75
+ - - ">="
58
76
  - !ruby/object:Gem::Version
59
77
  version: '0'
60
78
  required_rubygems_version: !ruby/object:Gem::Requirement
61
79
  requirements:
62
- - - ! '>='
80
+ - - ">="
63
81
  - !ruby/object:Gem::Version
64
82
  version: '0'
65
83
  requirements: []
66
84
  rubyforge_project:
67
- rubygems_version: 2.1.11
85
+ rubygems_version: 2.4.8
68
86
  signing_key:
69
87
  specification_version: 4
70
88
  summary: Extend a Aliyun OSS storage for paperclip
71
89
  test_files: []
90
+ has_rdoc: