tori 0.6.6 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e11c2e0db7bb0f1a6c31deecc5a07f21d38b8f56
4
- data.tar.gz: f6b4c1abe7704d7b6e0718993771cb7842ee9c7c
2
+ SHA256:
3
+ metadata.gz: c3f5c0fb1cf2098cfb8ce401f8627fba1b88c25b1a95a14df1dfe00d38296a1e
4
+ data.tar.gz: d905f6ecfe1a49fd9c648e2aabd3423079af98bcd9e18efd1cabcd6f199b78f2
5
5
  SHA512:
6
- metadata.gz: 0bc44fe133ca9d2192066f6a01bd2f3f252f5994b48fa08b6614282fd7a96b56fcbab13dbafdb4ad7e05e6e9c281e92de7dc5e5f381bf0c3e874f3c6515972bf
7
- data.tar.gz: e051c4febe852bbc5f37f4978ee4cd67db08bbd561575b3affaabdd73d5cf1195c94e9ca4032ec5b3ada5c85551ab7548580db3c622c23bf81c6cbeaf8af230f
6
+ metadata.gz: 81fef0f07412e79e59a691b520de8dace5a50d1a1870a4a134fe4fa10f9ce6188544abf7e898eb206a7cfd106e2e3630bc97d15f13c86c3eabc65e06c2b75543
7
+ data.tar.gz: 6ae9bef76edb139011bb8214b6b047e1934799f37afc078e62a0cad146e9a9216371500612839e941779c5bf0f10a6de9c5e1d02454af4079b4bc70978421cdd
@@ -0,0 +1,33 @@
1
+ name: test
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ pull_request:
9
+ branches:
10
+ - "*"
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ name: Ruby ${{ matrix.ruby }}
16
+ strategy:
17
+ matrix:
18
+ ruby:
19
+ - '3.1'
20
+ - '3.0'
21
+ - '2.7'
22
+ - '2.6'
23
+ - '2.5'
24
+ - '2.4'
25
+ - '2.3'
26
+
27
+ steps:
28
+ - uses: actions/checkout@v2
29
+ - uses: ruby/setup-ruby@v1
30
+ with:
31
+ ruby-version: ${{ matrix.ruby }}
32
+ bundler-cache: true
33
+ - run: bundle exec rake test
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  Tori
2
2
  ===
3
3
 
4
- [![Build Status](https://travis-ci.org/ksss/tori.svg?branch=master)](https://travis-ci.org/ksss/tori)
4
+ [![test](https://github.com/ksss/tori/actions/workflows/test.yml/badge.svg)](https://github.com/ksss/tori/actions/workflows/test.yml)
5
5
 
6
6
  "(\\( ⁰⊖⁰)/)"
7
7
 
8
8
  Tori is a very very simple file uploader.
9
9
 
10
- Tori dose nothing.
10
+ Tori does nothing.
11
11
 
12
12
  Only file upload to backend store.
13
13
 
@@ -121,29 +121,6 @@ class PhotoController < ApplicationController
121
121
  end
122
122
  ```
123
123
 
124
- # Custom configure example
125
-
126
- ```ruby
127
- # Save to S3 bucket.
128
- require 'tori/backend/s3'
129
- Tori.config.backend = Tori::Backend::S3.new(bucket: 'tori_bucket')
130
-
131
- # Filename decided by model.class.name,id and hidden words.
132
- Tori.config.filename_callback do |model|
133
- "#{model.class.name}/#{Digest::SHA1.hexdigest "#{ENV["TORI_MAGICKWORD"]}/#{model.id}"}"
134
- end
135
-
136
- # You can change any way define filename.
137
- Tori.config.filename_callback do |model|
138
- # `__tori__` method is meta name of defined by `tori` method.
139
- "#{model.class.name}/#{__tori__}/#{model.title}"
140
- # class Photo
141
- # tori :orig #=> "Photo/orig/cool-shot.png"
142
- # tori :strip #=> "Photo/strip/cool-shot.png"
143
- # end
144
- end
145
- ```
146
-
147
124
  # Default configure
148
125
 
149
126
  [https://github.com/ksss/tori/blob/master/lib/tori.rb](https://github.com/ksss/tori/blob/master/lib/tori.rb)
@@ -1,3 +1,5 @@
1
+ require 'ruby2_keywords'
2
+
1
3
  module Tori
2
4
  module Backend
3
5
  class FileSystem
@@ -45,12 +47,41 @@ module Tori
45
47
  end
46
48
  alias exists? exist?
47
49
 
48
- def read(filename, **args)
49
- ::File.read(path(filename), { mode: 'rb' }.merge(args))
50
+ if RUBY_VERSION < '2.7'
51
+ ruby2_keywords def read(filename, *args)
52
+ if args.last.kind_of?(Hash)
53
+ opt = args.pop
54
+ else
55
+ opt = {}
56
+ end
57
+ open(filename, {mode: 'rb'}.merge(opt)) do |f|
58
+ f.read(*args)
59
+ end
60
+ end
61
+
62
+ ruby2_keywords def open(filename, *rest, &block)
63
+ ::File.open(path(filename), *rest, &block)
64
+ end
65
+ else
66
+ def read(filename, len=nil, **args)
67
+ open(filename, **{mode: 'rb'}.merge(args)) do |f|
68
+ f.read(len)
69
+ end
70
+ end
71
+
72
+ def open(filename, **rest, &block)
73
+ ::File.open(path(filename), **rest, &block)
74
+ end
50
75
  end
51
76
 
52
- def open(filename, *rest, &block)
53
- ::File.open(path(filename), *rest, &block)
77
+ def copy_to(filename, tori_file, **opts)
78
+ FileUtils.mkdir_p tori_file.path.dirname
79
+
80
+ ::File.open(path(filename)) do |from|
81
+ ::File.open(tori_file.path, 'w+') do |to|
82
+ IO.copy_stream(from, to)
83
+ end
84
+ end
54
85
  end
55
86
 
56
87
  def path(filename)
@@ -1,4 +1,4 @@
1
- require 'aws-sdk-core'
1
+ require 'aws-sdk-s3'
2
2
  require 'mime/types'
3
3
 
4
4
  module Tori
@@ -57,6 +57,10 @@ module Tori
57
57
  opts[:content_type] = self.class.type_for(from_path)
58
58
  end
59
59
 
60
+ if resource.nil? && opts[:body]
61
+ resource = opts[:body]
62
+ end
63
+
60
64
  case resource
61
65
  when String
62
66
  put_object({
@@ -121,6 +125,15 @@ module Tori
121
125
  end
122
126
  end
123
127
 
128
+ def copy_to(filename, tori_file, **opts)
129
+ copy_object(
130
+ copy_source: "#{bucket}/#{filename}",
131
+ bucket: bucket,
132
+ key: tori_file.name,
133
+ **opts,
134
+ )
135
+ end
136
+
124
137
  def public_url(filename)
125
138
  "#{client.config.endpoint}/#{@bucket}/#{filename}"
126
139
  end
@@ -135,12 +148,12 @@ module Tori
135
148
  tmpdir = opts.delete(:tmpdir)
136
149
 
137
150
  if block_given?
138
- Tempfile.create(names, tmpdir, opts) do |f|
151
+ Tempfile.create(names, tmpdir, **opts) do |f|
139
152
  get_object(key: filename, response_target: f.path)
140
153
  yield f
141
154
  end
142
155
  else
143
- f = Tempfile.open(names, tmpdir, opts)
156
+ f = Tempfile.open(names, tmpdir, **opts)
144
157
  get_object(key: filename, response_target: f.path)
145
158
  f
146
159
  end
@@ -169,6 +182,10 @@ module Tori
169
182
  def delete_object(opts={})
170
183
  client.delete_object bucket: @bucket, **opts
171
184
  end
185
+
186
+ def copy_object(opts = {})
187
+ client.copy_object bucket: @bucket, **opts
188
+ end
172
189
  end
173
190
  end
174
191
  end
data/lib/tori/file.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'ruby2_keywords'
2
+
1
3
  module Tori
2
4
  class File
3
5
  def initialize(model, title: nil, from: nil, to: nil, &block)
@@ -65,12 +67,24 @@ module Tori
65
67
  backend.respond_to?(sym, include_private)
66
68
  end
67
69
 
68
- def method_missing(sym, *args, &block)
69
- if respond_to_missing?(sym, false)
70
- backend.__send__ sym, name, *args, &block
71
- else
72
- raise NameError, "undefined method `#{sym}' for #{backend}"
70
+ if RUBY_VERSION < "2.7"
71
+ ruby2_keywords def method_missing(sym, *args, &block)
72
+ if respond_to_missing?(sym, false)
73
+ backend.__send__ sym, name, *args, &block
74
+ else
75
+ raise NameError, "undefined method `#{sym}' for #{backend}"
76
+ end
73
77
  end
78
+ else
79
+ eval <<~'RUBY'
80
+ def method_missing(sym, ...)
81
+ if respond_to_missing?(sym, false)
82
+ backend.__send__(sym, name, ...)
83
+ else
84
+ raise NameError, "undefined method `#{sym}' for #{backend}"
85
+ end
86
+ end
87
+ RUBY
74
88
  end
75
89
  end
76
90
  end
data/lib/tori/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tori
2
- VERSION = "0.6.6"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -0,0 +1,10 @@
1
+ Aws.config[:s3] = {
2
+ stub_responses: {
3
+ head_bucket: {},
4
+ get_object: {
5
+ content_type: "text/plain",
6
+ body: "foo",
7
+ content_length: 3,
8
+ }
9
+ }
10
+ }
@@ -34,6 +34,7 @@ class TestToriBackendFileSystem < Test::Unit::TestCase
34
34
  File.open(@filesystem.root.join("utf8file"), 'wb') { |f| f.write utf8 }
35
35
  assert { utf8 != @filesystem.read("utf8file") }
36
36
  assert { utf8 == @filesystem.read("utf8file", external_encoding: Encoding::UTF_8) }
37
+ assert { "\xE3".b == @filesystem.read("utf8file", 1) }
37
38
 
38
39
  assert { Encoding::ASCII_8BIT == @filesystem.read("binfile").encoding }
39
40
  assert { Encoding::UTF_8 == @filesystem.read("binfile", external_encoding: Encoding::UTF_8).encoding }
@@ -1,10 +1,10 @@
1
1
  require 'test_helper'
2
2
  require 'tori/backend/s3'
3
-
4
- if ENV["TORI_TEST_BUCKET"]
3
+ require_relative 'aws_s3_stub'
5
4
 
6
5
  class TestToriBackendS3 < Test::Unit::TestCase
7
6
  BucketNotFoundError = Class.new(StandardError)
7
+ TORI_TEST_BUCKET = 'tori-testing-bucket'
8
8
  def request_head(url)
9
9
  uri = URI.parse(url)
10
10
  req = Net::HTTP::Head.new(uri.path)
@@ -14,7 +14,7 @@ class TestToriBackendS3 < Test::Unit::TestCase
14
14
  end
15
15
 
16
16
  setup do
17
- @backend = Tori::Backend::S3.new(bucket: ENV["TORI_TEST_BUCKET"])
17
+ @backend = Tori::Backend::S3.new(bucket: TORI_TEST_BUCKET, client: Aws::S3::Client.new)
18
18
  fail BucketNotFoundError, "S3 test need make s3 bucket '#{@backend.bucket}'" unless @backend.exists?
19
19
 
20
20
  @testfile_path = Pathname.new("test/tmp/testfile")
@@ -28,16 +28,7 @@ class TestToriBackendS3 < Test::Unit::TestCase
28
28
  end
29
29
 
30
30
  test "auto content_type" do
31
- Tempfile.create(["test", ".jpeg"]) do |f|
32
- file = Tori::File.new(:dummy, from: f, to: @backend){ |model| "test-key" }
33
- begin
34
- file.write
35
- content_type = file.get.content_type
36
- assert { 'image/jpeg' == content_type }
37
- ensure
38
- file.delete
39
- end
40
- end
31
+ assert { 'image/jpeg' == Tori::Backend::S3.type_for("test.jpeg") }
41
32
  end
42
33
 
43
34
  test "#initialize" do
@@ -46,7 +37,7 @@ class TestToriBackendS3 < Test::Unit::TestCase
46
37
  assert { ENV["TORI_AWS_SECRET_ACCESS_KEY"] == @backend.client.config.secret_access_key }
47
38
 
48
39
  custom_backend = Tori::Backend::S3.new(
49
- bucket: ENV["TORI_TEST_BUCKET"],
40
+ bucket: TORI_TEST_BUCKET,
50
41
  client: Aws::S3::Client.new(access_key_id: 'aaa', secret_access_key: 'bbb'),
51
42
  )
52
43
  assert_instance_of Tori::Backend::S3, custom_backend
@@ -56,7 +47,7 @@ class TestToriBackendS3 < Test::Unit::TestCase
56
47
  assert_raise(ArgumentError){ Tori::Backend::S3.new }
57
48
  assert_raise(TypeError) {
58
49
  Tori::Backend::S3.new(
59
- bucket: ENV["TORI_TEST_BUCKET"],
50
+ bucket: TORI_TEST_BUCKET,
60
51
  client: Object.new,
61
52
  )
62
53
  }
@@ -69,9 +60,9 @@ class TestToriBackendS3 < Test::Unit::TestCase
69
60
  end
70
61
 
71
62
  test "#write String" do
72
- @backend.write("testfile", "foo", content_type: "image/png")
63
+ @backend.write("testfile", "foo", content_type: "text/plain")
73
64
  testfile = @backend.get_object(key: "testfile")
74
- assert { "image/png" == testfile.content_type }
65
+ assert { "text/plain" == testfile.content_type }
75
66
  assert { "foo" == testfile[:body].read }
76
67
  end
77
68
 
@@ -79,21 +70,15 @@ class TestToriBackendS3 < Test::Unit::TestCase
79
70
  assert_nothing_raised { @backend.write("testfile", @testfile_path) }
80
71
  testfile = @backend.get_object(key: "testfile")
81
72
  assert { "text/plain" == testfile.content_type }
82
- assert { 4 == testfile.content_length }
83
- assert { "text" == testfile[:body].read }
84
-
85
- @backend.write("testfile", @testfile_path, acl: "public-read-write")
86
- res = request_head(@backend.public_url("testfile"))
87
- assert { Net::HTTPOK === res}
73
+ assert { 3 == testfile.content_length }
74
+ assert { "foo" == testfile[:body].read }
88
75
 
89
- @backend.write("testfile", @testfile_path, acl: "private")
90
- res = request_head(@backend.public_url("testfile"))
91
- assert { Net::HTTPForbidden === res}
76
+ assert_nothing_raised { @backend.write("testfile", @testfile_path, acl: "public-read-write") }
77
+ assert_nothing_raised { @backend.write("testfile", @testfile_path, acl: "private") }
92
78
  end
93
79
 
94
80
  test "#read" do
95
- assert_equal "text", @backend.read("testfile")
96
- assert_raise(Aws::S3::Errors::NoSuchKey) { @backend.read("testfile", key: "nothing") }
81
+ assert_equal "foo", @backend.read("testfile")
97
82
  end
98
83
 
99
84
  test "#exists?" do
@@ -103,11 +88,10 @@ class TestToriBackendS3 < Test::Unit::TestCase
103
88
 
104
89
  test "#delete" do
105
90
  assert_nothing_raised { @backend.delete("testfile") }
106
- assert { false == @backend.exists?("testfile") }
107
91
  end
108
92
 
109
93
  test "#public_url" do
110
- assert_match %r!https?://s3-!, @backend.public_url("testfile")
94
+ assert_match %r!https?://s3!, @backend.public_url("testfile")
111
95
  assert_match @backend.bucket, @backend.public_url("testfile")
112
96
  assert_match "testfile", @backend.public_url("testfile")
113
97
  end
@@ -116,7 +100,7 @@ class TestToriBackendS3 < Test::Unit::TestCase
116
100
  path = nil
117
101
  @backend.open("testfile") do |f|
118
102
  assert_instance_of File, f
119
- assert { "text" == f.read }
103
+ assert { "foo" == f.read }
120
104
  path = f.path
121
105
  end
122
106
  assert { false == File.exist?(path) }
@@ -128,9 +112,15 @@ class TestToriBackendS3 < Test::Unit::TestCase
128
112
  @backend.write("path/to/file", @testfile_path)
129
113
  @backend.open("path/to/file") do |f|
130
114
  assert_instance_of File, f
131
- assert { "text" == f.read }
115
+ assert { "foo" == f.read }
132
116
  end
133
117
  end
134
- end
135
118
 
119
+ test "#copy_to" do
120
+ o = Object.new
121
+ file = Tori::File.new(o) do |model|
122
+ model.object_id.to_s
123
+ end
124
+ @backend.copy_to("copy_to_file", file)
125
+ end
136
126
  end
@@ -10,7 +10,7 @@ class TestToriFile < Test::Unit::TestCase
10
10
  end
11
11
 
12
12
  teardown do
13
- Tori.config.filename_callback &@orig
13
+ Tori.config.filename_callback(&@orig)
14
14
  FileUtils.rm_rf("test/tmp")
15
15
  end
16
16
 
@@ -18,7 +18,7 @@ class TestToriFile < Test::Unit::TestCase
18
18
  def rewind
19
19
  end
20
20
 
21
- def read
21
+ def read(*)
22
22
  __FILE__
23
23
  end
24
24
  end
@@ -57,6 +57,14 @@ class TestToriFile < Test::Unit::TestCase
57
57
  assert { true == File.exist?("test/tmp/copy") }
58
58
  end
59
59
 
60
+ test "write with body" do
61
+ assert { false == File.exist?("test/tmp/copy") }
62
+ Tori::File.new("copy").write(
63
+ body: From.new,
64
+ )
65
+ assert { true == File.exist?("test/tmp/copy") }
66
+ end
67
+
60
68
  test "backend" do
61
69
  assert { Tori.config.backend == Tori::File.new(nil).backend }
62
70
  end
@@ -90,12 +98,12 @@ class TestToriFile < Test::Unit::TestCase
90
98
  end
91
99
  assert { "test/" == Tori::File.new("test").name }
92
100
  assert { "test/tori" == Tori::File.new("test", title: "tori").name }
93
- Tori.config.filename_callback &before
101
+ Tori.config.filename_callback(&before)
94
102
  end
95
103
 
96
104
  test "#method_missing" do
97
105
  assert { true == Tori::File.new(nil).respond_to?(:read) }
98
106
  assert_raise(NameError) { Tori::File.new(nil).undefined }
99
- assert { [true, Encoding.find('utf-8'), 'test/tmp'] == Tori::File.new(nil).open('rb', external_encoding: 'utf-8'){ |f| [f.binmode?, f.external_encoding, f.path] } }
107
+ assert { [true, Encoding.find('utf-8'), 'test/tmp'] == Tori::File.new(nil).open(mode: 'rb', external_encoding: 'utf-8'){ |f| [f.binmode?, f.external_encoding, f.path] } }
100
108
  end
101
109
  end
data/tori.gemspec CHANGED
@@ -17,8 +17,10 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_runtime_dependency "aws-sdk-core"
20
+ spec.add_runtime_dependency "aws-sdk-s3"
21
21
  spec.add_runtime_dependency "mime-types"
22
+ spec.add_runtime_dependency 'rexml'
23
+ spec.add_runtime_dependency 'ruby2_keywords'
22
24
  spec.add_development_dependency "bundler"
23
25
  spec.add_development_dependency "rake"
24
26
  spec.add_development_dependency "test-unit"
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tori
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.6
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-29 00:00:00.000000000 Z
11
+ date: 2022-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: aws-sdk-core
14
+ name: aws-sdk-s3
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rexml
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruby2_keywords
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: bundler
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -87,8 +115,8 @@ executables: []
87
115
  extensions: []
88
116
  extra_rdoc_files: []
89
117
  files:
118
+ - ".github/workflows/test.yml"
90
119
  - ".gitignore"
91
- - ".travis.yml"
92
120
  - Gemfile
93
121
  - LICENSE.txt
94
122
  - README.md
@@ -103,6 +131,7 @@ files:
103
131
  - lib/tori/file.rb
104
132
  - lib/tori/rails.rb
105
133
  - lib/tori/version.rb
134
+ - test/aws_s3_stub.rb
106
135
  - test/test_helper.rb
107
136
  - test/test_tori.rb
108
137
  - test/test_tori_backend_chain.rb
@@ -131,12 +160,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
160
  - !ruby/object:Gem::Version
132
161
  version: '0'
133
162
  requirements: []
134
- rubyforge_project:
135
- rubygems_version: 2.6.1
163
+ rubygems_version: 3.3.3
136
164
  signing_key:
137
165
  specification_version: 4
138
166
  summary: Simple file uploader
139
167
  test_files:
168
+ - test/aws_s3_stub.rb
140
169
  - test/test_helper.rb
141
170
  - test/test_tori.rb
142
171
  - test/test_tori_backend_chain.rb
data/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.1.8
4
- - 2.2.4
5
- - 2.3.0
6
- notifications:
7
- email: false