tori 0.6.6 → 0.8.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
- 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