refile 0.2.5 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +6 -0
- data/README.md +28 -0
- data/Rakefile +5 -0
- data/config/locales/en.yml +1 -0
- data/lib/refile.rb +95 -2
- data/lib/refile/app.rb +1 -0
- data/lib/refile/attachment.rb +34 -10
- data/lib/refile/attachment/active_record.rb +3 -0
- data/lib/refile/backend/s3.rb +3 -0
- data/lib/refile/rails.rb +0 -11
- data/lib/refile/rails/attachment_helper.rb +1 -0
- data/lib/refile/random_hasher.rb +5 -0
- data/lib/refile/version.rb +1 -1
- data/refile.gemspec +3 -0
- data/spec/refile/attachment_spec.rb +58 -0
- data/spec/refile/features/normal_upload_spec.rb +13 -0
- data/spec/refile/spec_helper.rb +6 -4
- data/spec/refile/test_app/app/controllers/normal_posts_controller.rb +1 -1
- data/spec/refile/test_app/app/views/normal_posts/_form.html.erb +4 -0
- metadata +45 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd423a66e8cd66e1dbb128aad4724806341335ea
|
4
|
+
data.tar.gz: 8eef6a2838a39c3d74b87fe03467905ea548145e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b2b30128fd4f7980a5b3e1b490fa47f17acf38c7bc458b0eec8a117856c90d087606341055ff1af77b9b37138849020a219c9cd59d6640ff30334595d4d6162
|
7
|
+
data.tar.gz: 4a01443db981b687b7933463cfa5a1a1837f8e16470cfdbf4d4fb3bf9f609d2334afebbb803c8735cf1836626ef1e3e0ace656ceae19bbce49132fbea873b2af
|
data/History.md
CHANGED
data/README.md
CHANGED
@@ -506,6 +506,34 @@ end
|
|
506
506
|
Now when you check this checkbox and submit the form, the previously attached
|
507
507
|
file will be removed.
|
508
508
|
|
509
|
+
## Fetching remote files by URL
|
510
|
+
|
511
|
+
You might want to give you users the option of uploading a file by its URL.
|
512
|
+
This could be either just via a textfield or through some other interface.
|
513
|
+
Refile makes it easy to fetch this file and upload it. Just add a field like
|
514
|
+
this:
|
515
|
+
|
516
|
+
``` erb
|
517
|
+
<%= form_for @user do |form| %>
|
518
|
+
<%= form.label :profile_image, "Attach image" %>
|
519
|
+
<%= form.attachment_field :profile_image %>
|
520
|
+
|
521
|
+
<%= form.label :remote_profile_image_url, "Or specify URL" %>
|
522
|
+
<%= form.text_field :remote_profile_image_url %>
|
523
|
+
<% end %>
|
524
|
+
```
|
525
|
+
|
526
|
+
Then permit this field in your controller:
|
527
|
+
|
528
|
+
``` ruby
|
529
|
+
def user_params
|
530
|
+
params.require(:user).permit(:profile_image, :profile_image_cache_id, :remote_profile_image_url)
|
531
|
+
end
|
532
|
+
```
|
533
|
+
|
534
|
+
Refile will now fetch the file from the given URL, following redirects if
|
535
|
+
needed.
|
536
|
+
|
509
537
|
## Cache expiry
|
510
538
|
|
511
539
|
Files will accumulate in your cache, and you'll probably want to remove them
|
data/Rakefile
CHANGED
@@ -3,6 +3,11 @@ $LOAD_PATH.unshift(File.expand_path("spec", File.dirname(__FILE__)))
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "refile/test_app"
|
5
5
|
require "rspec/core/rake_task"
|
6
|
+
require "yard"
|
7
|
+
|
8
|
+
YARD::Rake::YardocTask.new do |t|
|
9
|
+
t.files = ["README.md", "lib/**/*.rb"]
|
10
|
+
end
|
6
11
|
|
7
12
|
RSpec::Core::RakeTask.new(:spec)
|
8
13
|
|
data/config/locales/en.yml
CHANGED
data/lib/refile.rb
CHANGED
@@ -1,47 +1,140 @@
|
|
1
1
|
require "uri"
|
2
2
|
require "fileutils"
|
3
3
|
require "tempfile"
|
4
|
+
require "rest_client"
|
4
5
|
|
5
6
|
module Refile
|
6
7
|
class Invalid < StandardError; end
|
7
8
|
|
8
9
|
class << self
|
9
|
-
attr_accessor :read_chunk_size, :app, :host, :direct_upload
|
10
|
-
attr_writer :store, :cache
|
11
10
|
|
11
|
+
# The number of bytes to read when files are streamed. Refile
|
12
|
+
# uses this in a couple of places where files should be streamed
|
13
|
+
# in a memory efficient way instead of reading the entire file into
|
14
|
+
# memory at once. The default value of this is `3000`.
|
15
|
+
#
|
16
|
+
# @return [Fixnum]
|
17
|
+
attr_accessor :read_chunk_size
|
18
|
+
|
19
|
+
# A shortcut to the instance of the Rack application. This should be
|
20
|
+
# set when the application is initialized. `refile/rails` sets this
|
21
|
+
# value.
|
22
|
+
#
|
23
|
+
# @return [Refile::App, nil]
|
24
|
+
attr_accessor :app
|
25
|
+
|
26
|
+
# The host name that the Rack application can be reached at. If not set,
|
27
|
+
# Refile will use an absolute URL without hostname. It is strongly
|
28
|
+
# recommended to run Refile behind a CDN and to set this to the hostname of
|
29
|
+
# the CDN distribution. A protocol relative URL is recommended for this
|
30
|
+
# value.
|
31
|
+
#
|
32
|
+
# @return [String, nil]
|
33
|
+
attr_accessor :host
|
34
|
+
|
35
|
+
# A list of names which identify backends in the global backend registry.
|
36
|
+
# The Rack application allows POST requests to only the backends specified
|
37
|
+
# in this config option. This defaults to `["cache"]`, only allowing direct
|
38
|
+
# uploads to the cache backend.
|
39
|
+
#
|
40
|
+
# @return [Array[String]]
|
41
|
+
attr_accessor :direct_upload
|
42
|
+
|
43
|
+
# A global registry of backends.
|
44
|
+
#
|
45
|
+
# @return [Hash{String => Backend}]
|
12
46
|
def backends
|
13
47
|
@backends ||= {}
|
14
48
|
end
|
15
49
|
|
50
|
+
# A global registry of processors. These will be used by the Rack
|
51
|
+
# application to manipulate files prior to serving them up to the user,
|
52
|
+
# based on options sent trough the URL. This can be used for example to
|
53
|
+
# resize images or to convert files to another file format.
|
54
|
+
#
|
55
|
+
# @return [Hash{String => Proc}]
|
16
56
|
def processors
|
17
57
|
@processors ||= {}
|
18
58
|
end
|
19
59
|
|
60
|
+
# Adds a processor. The processor must respond to `call`, both receiving
|
61
|
+
# and returning an IO-like object. Alternatively a block can be given to
|
62
|
+
# this method which also receives and returns an IO-like object.
|
63
|
+
#
|
64
|
+
# An IO-like object is recommended to be an instance of the `IO` class or
|
65
|
+
# one of its subclasses, like `File` or a `StringIO`, or a `Refile::File`.
|
66
|
+
# It can also be any other object which responds to `size`, `read`, `eof`?
|
67
|
+
# and `close` and mimics the behaviour of IO objects for these methods.
|
68
|
+
#
|
69
|
+
# @example With processor class
|
70
|
+
# class Reverse
|
71
|
+
# def call(file)
|
72
|
+
# StringIO.new(file.read.reverse)
|
73
|
+
# en
|
74
|
+
# end
|
75
|
+
# Refile.processor(:reverse, Reverse)
|
76
|
+
#
|
77
|
+
# @example With block
|
78
|
+
# Refile.processor(:reverse) do |file|
|
79
|
+
# StringIO.new(file.read.reverse)
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# @param [#to_s] name The name of the processor
|
83
|
+
# @param [Proc, nil] processor The processor, must respond to `call` and.
|
84
|
+
# @yield [Refile::File] The file to modify
|
85
|
+
# @yieldreturn [IO] An IO-like object representing the processed file
|
20
86
|
def processor(name, processor = nil, &block)
|
21
87
|
processor ||= block
|
22
88
|
processors[name.to_s] = processor
|
23
89
|
end
|
24
90
|
|
91
|
+
# A shortcut to retrieving the backend named "store" from the global
|
92
|
+
# registry.
|
93
|
+
#
|
94
|
+
# @return [Backend]
|
25
95
|
def store
|
26
96
|
backends["store"]
|
27
97
|
end
|
28
98
|
|
99
|
+
# A shortcut to setting the backend named "store" in the global registry.
|
100
|
+
#
|
101
|
+
# @param [Backend] backend
|
29
102
|
def store=(backend)
|
30
103
|
backends["store"] = backend
|
31
104
|
end
|
32
105
|
|
106
|
+
# A shortcut to retrieving the backend named "cache" from the global
|
107
|
+
# registry.
|
108
|
+
#
|
109
|
+
# @return [Backend]
|
33
110
|
def cache
|
34
111
|
backends["cache"]
|
35
112
|
end
|
36
113
|
|
114
|
+
# A shortcut to setting the backend named "cache" in the global registry.
|
115
|
+
#
|
116
|
+
# @param [Backend] backend
|
37
117
|
def cache=(backend)
|
38
118
|
backends["cache"] = backend
|
39
119
|
end
|
40
120
|
|
121
|
+
# Yield the Refile module as a convenience for configuring multiple
|
122
|
+
# config options at once.
|
123
|
+
#
|
124
|
+
# @yield Refile
|
41
125
|
def configure
|
42
126
|
yield self
|
43
127
|
end
|
44
128
|
|
129
|
+
# Verify that the given uploadable is indeed a valid uploadable. This
|
130
|
+
# method is used by backends as a sanity check, you should not have to use
|
131
|
+
# this method unless you are writing a backend.
|
132
|
+
#
|
133
|
+
# @param [IO] uploadable The uploadable object to verify
|
134
|
+
# @param [Fixnum] max_size The maximum size of the uploadable object
|
135
|
+
# @raise [ArgumentError] If the uploadable is not an IO-like object
|
136
|
+
# @raise [Refile::Invalid] If the uploadable's size is too large
|
137
|
+
# @return [true] Always returns true if it doesn't raise
|
45
138
|
def verify_uploadable(uploadable, max_size)
|
46
139
|
[:size, :read, :eof?, :close].each do |m|
|
47
140
|
unless uploadable.respond_to?(m)
|
data/lib/refile/app.rb
CHANGED
data/lib/refile/attachment.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module Refile
|
2
2
|
module Attachment
|
3
|
-
|
4
|
-
|
3
|
+
# @api private
|
5
4
|
class Attachment
|
6
|
-
attr_reader :record, :name, :cache, :store, :cache_id, :options
|
5
|
+
attr_reader :record, :name, :cache, :store, :cache_id, :options, :errors
|
7
6
|
attr_accessor :remove
|
8
7
|
|
9
8
|
def initialize(record, name, **options)
|
@@ -24,7 +23,7 @@ module Refile
|
|
24
23
|
end
|
25
24
|
|
26
25
|
def file
|
27
|
-
if
|
26
|
+
if cached?
|
28
27
|
cache.get(cache_id)
|
29
28
|
elsif id and not id == ""
|
30
29
|
store.get(id)
|
@@ -40,6 +39,16 @@ module Refile
|
|
40
39
|
raise if @options[:raise_errors]
|
41
40
|
end
|
42
41
|
|
42
|
+
def download(url)
|
43
|
+
if url and not url == ""
|
44
|
+
raw_response = RestClient::Request.new(method: :get, url: url, raw_response: true).execute
|
45
|
+
self.file = raw_response.file
|
46
|
+
end
|
47
|
+
rescue RestClient::Exception
|
48
|
+
@errors = [:download_failed]
|
49
|
+
raise if @options[:raise_errors]
|
50
|
+
end
|
51
|
+
|
43
52
|
def cache_id=(id)
|
44
53
|
@cache_id = id unless @cache_file
|
45
54
|
end
|
@@ -65,20 +74,28 @@ module Refile
|
|
65
74
|
end
|
66
75
|
|
67
76
|
def remove?
|
68
|
-
remove
|
77
|
+
remove and remove != "" and remove !~ /\A0|false$\z/
|
69
78
|
end
|
70
79
|
|
71
|
-
|
72
|
-
@errors
|
73
|
-
end
|
74
|
-
|
75
|
-
private
|
80
|
+
private
|
76
81
|
|
77
82
|
def cached?
|
78
83
|
cache_id and not cache_id == ""
|
79
84
|
end
|
80
85
|
end
|
81
86
|
|
87
|
+
# Macro which generates accessors for the given column which make it
|
88
|
+
# possible to upload and retrieve previously uploaded files through the
|
89
|
+
# generated accessors.
|
90
|
+
#
|
91
|
+
# The +raise_errors+ option controls whether assigning an invalid file
|
92
|
+
# should immediately raise an error, or save the error and defer handling
|
93
|
+
# it until later.
|
94
|
+
#
|
95
|
+
# @param [String] name Name of the column which accessor are generated for
|
96
|
+
# @param [#to_s] cache Name of a backend in +Refile.backends+ to use as transient cache
|
97
|
+
# @param [#to_s] store Name of a backend in +Refile.backends+ to use as permanent store
|
98
|
+
# @param [true, false] raise_errors Whether to raise errors in case an invalid file is assigned
|
82
99
|
def attachment(name, cache: :cache, store: :store, raise_errors: true)
|
83
100
|
attachment = :"#{name}_attachment"
|
84
101
|
|
@@ -112,6 +129,13 @@ module Refile
|
|
112
129
|
define_method "remove_#{name}" do
|
113
130
|
send(attachment).remove
|
114
131
|
end
|
132
|
+
|
133
|
+
define_method "remote_#{name}_url=" do |url|
|
134
|
+
send(attachment).download(url)
|
135
|
+
end
|
136
|
+
|
137
|
+
define_method "remote_#{name}_url" do
|
138
|
+
end
|
115
139
|
end
|
116
140
|
end
|
117
141
|
end
|
data/lib/refile/backend/s3.rb
CHANGED
@@ -2,7 +2,10 @@ require "aws-sdk"
|
|
2
2
|
|
3
3
|
module Refile
|
4
4
|
module Backend
|
5
|
+
|
6
|
+
# A refile backend which stores files in Amazon S3
|
5
7
|
class S3
|
8
|
+
|
6
9
|
# Emulates an IO-object like interface on top of S3Object#read. To avoid
|
7
10
|
# memory allocations and unnecessary complexity, this treats the `length`
|
8
11
|
# parameter to read as a boolean flag instead. If given, it will read the
|
data/lib/refile/rails.rb
CHANGED
@@ -2,17 +2,6 @@ require "refile"
|
|
2
2
|
require "refile/rails/attachment_helper"
|
3
3
|
|
4
4
|
module Refile
|
5
|
-
module Controller
|
6
|
-
def show
|
7
|
-
file = Refile.backends.fetch(params[:backend_name]).get(params[:id])
|
8
|
-
|
9
|
-
options = { disposition: "inline" }
|
10
|
-
options[:type] = Mime::Type.lookup_by_extension(params[:format]).to_s if params[:format]
|
11
|
-
|
12
|
-
send_data file.read, options
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
5
|
module AttachmentFieldHelper
|
17
6
|
def attachment_field(method, options = {})
|
18
7
|
self.multipart = true
|
data/lib/refile/random_hasher.rb
CHANGED
data/lib/refile/version.rb
CHANGED
data/refile.gemspec
CHANGED
@@ -18,7 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.require_paths = ["lib", "spec"]
|
19
19
|
|
20
20
|
spec.required_ruby_version = ">= 2.1.0"
|
21
|
+
spec.add_dependency "rest-client", "~> 1.7.2"
|
21
22
|
|
23
|
+
spec.add_development_dependency "webmock", "~> 1.20.4"
|
22
24
|
spec.add_development_dependency "bundler", "~> 1.6"
|
23
25
|
spec.add_development_dependency "rake"
|
24
26
|
spec.add_development_dependency "rspec", "~> 3.0"
|
@@ -31,4 +33,5 @@ Gem::Specification.new do |spec|
|
|
31
33
|
spec.add_development_dependency "rails", "~> 4.1.8"
|
32
34
|
spec.add_development_dependency "sqlite3"
|
33
35
|
spec.add_development_dependency "selenium-webdriver"
|
36
|
+
spec.add_development_dependency "yard"
|
34
37
|
end
|
@@ -31,6 +31,64 @@ describe Refile::Attachment do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
describe "remote_:name_url=" do
|
35
|
+
it "does nothign when nil is assigned" do
|
36
|
+
instance.remote_document_url = nil
|
37
|
+
expect(instance.document).to be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it "does nothign when empty string is assigned" do
|
41
|
+
instance.remote_document_url = nil
|
42
|
+
expect(instance.document).to be_nil
|
43
|
+
end
|
44
|
+
|
45
|
+
context "without redirects" do
|
46
|
+
before(:each) do
|
47
|
+
stub_request(:get, "http://www.example.com/some_file").to_return(status: 200, body: "abc", headers: { "Content-Length" => 3 })
|
48
|
+
end
|
49
|
+
|
50
|
+
it "downloads file, caches it and sets the _id parameter" do
|
51
|
+
instance.remote_document_url = "http://www.example.com/some_file"
|
52
|
+
expect(Refile.cache.get(instance.document.id).read).to eq("abc")
|
53
|
+
expect(Refile.cache.get(instance.document_cache_id).read).to eq("abc")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with redirects" do
|
58
|
+
before(:each) do
|
59
|
+
stub_request(:get, "http://www.example.com/1").to_return(status: 302, headers: { "Location" => "http://www.example.com/2" })
|
60
|
+
stub_request(:get, "http://www.example.com/2").to_return(status: 200, body: "woop", headers: { "Content-Length" => 4 })
|
61
|
+
stub_request(:get, "http://www.example.com/loop").to_return(status: 302, headers: { "Location" => "http://www.example.com/loop" })
|
62
|
+
end
|
63
|
+
|
64
|
+
it "follows redirects and fetches the file, caches it and sets the _id parameter" do
|
65
|
+
instance.remote_document_url = "http://www.example.com/1"
|
66
|
+
expect(Refile.cache.get(instance.document.id).read).to eq("woop")
|
67
|
+
expect(Refile.cache.get(instance.document_cache_id).read).to eq("woop")
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when errors enabled" do
|
71
|
+
let(:options) { { raise_errors: true } }
|
72
|
+
it "handles redirect loops by trowing errors" do
|
73
|
+
expect do
|
74
|
+
instance.remote_document_url = "http://www.example.com/loop"
|
75
|
+
end.to raise_error(RestClient::MaxRedirectsReached)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when errors disabled" do
|
80
|
+
let(:options) { { raise_errors: false } }
|
81
|
+
it "handles redirect loops by setting generic download error" do
|
82
|
+
expect do
|
83
|
+
instance.remote_document_url = "http://www.example.com/loop"
|
84
|
+
end.not_to raise_error
|
85
|
+
expect(instance.document_attachment.errors).to eq([:download_failed])
|
86
|
+
expect(instance.document).to be_nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
34
92
|
describe ":name_cache_id" do
|
35
93
|
it "doesn't overwrite a cached file" do
|
36
94
|
instance.document = Refile::FileDouble.new("hello")
|
@@ -60,4 +60,17 @@ feature "Normal HTTP Post file uploads" do
|
|
60
60
|
expect(page).to have_selector("h1", text: "A cool post")
|
61
61
|
expect(page).to_not have_selector(:link, "Document")
|
62
62
|
end
|
63
|
+
|
64
|
+
scenario "Upload a file from a remote URL" do
|
65
|
+
stub_request(:get, "http://www.example.com/some_file").to_return(status: 200, body: "abc", headers: { "Content-Length" => 3 })
|
66
|
+
|
67
|
+
visit "/normal/posts/new"
|
68
|
+
fill_in "Title", with: "A cool post"
|
69
|
+
fill_in "Remote document url", with: "http://www.example.com/some_file"
|
70
|
+
click_button "Create"
|
71
|
+
|
72
|
+
expect(page).to have_selector("h1", text: "A cool post")
|
73
|
+
click_link("Document")
|
74
|
+
expect(page.source.chomp).to eq("abc")
|
75
|
+
end
|
63
76
|
end
|
data/spec/refile/spec_helper.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "refile"
|
2
2
|
require "refile/backend_examples"
|
3
|
+
require "webmock/rspec"
|
3
4
|
|
4
5
|
tmp_path = Dir.mktmpdir
|
5
6
|
|
@@ -15,13 +16,13 @@ class FakePresignBackend < Refile::Backend::FileSystem
|
|
15
16
|
|
16
17
|
def presign
|
17
18
|
id = Refile::RandomHasher.new.hash
|
18
|
-
Signature.new("file", id, "/presigned/posts/upload",
|
19
|
+
Signature.new("file", id, "/presigned/posts/upload", token: "xyz123", id: id)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
23
|
Refile.backends["limited_cache"] = FakePresignBackend.new(File.expand_path("default_cache", tmp_path), max_size: 100)
|
23
24
|
|
24
|
-
Refile.direct_upload =
|
25
|
+
Refile.direct_upload = %w(cache limited_cache)
|
25
26
|
|
26
27
|
Refile.processor(:reverse) do |file|
|
27
28
|
StringIO.new(file.read.reverse)
|
@@ -48,7 +49,6 @@ Refile.processor(:convert_case) do |file, format:|
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
|
-
|
52
52
|
class Refile::FileDouble
|
53
53
|
def initialize(data)
|
54
54
|
@io = StringIO.new(data)
|
@@ -79,5 +79,7 @@ end
|
|
79
79
|
|
80
80
|
RSpec.configure do |config|
|
81
81
|
config.include PathHelper
|
82
|
+
config.before(:all) do
|
83
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
84
|
+
end
|
82
85
|
end
|
83
|
-
|
@@ -34,6 +34,6 @@ class NormalPostsController < ApplicationController
|
|
34
34
|
private
|
35
35
|
|
36
36
|
def post_params
|
37
|
-
params.require(:post).permit(:title, :image, :image_cache_id, :document, :document_cache_id, :remove_document)
|
37
|
+
params.require(:post).permit(:title, :image, :image_cache_id, :document, :document_cache_id, :remove_document, :remote_document_url)
|
38
38
|
end
|
39
39
|
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: refile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Nicklas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.7.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.7.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: webmock
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.20.4
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.20.4
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: bundler
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,6 +206,20 @@ dependencies:
|
|
178
206
|
- - ">="
|
179
207
|
- !ruby/object:Gem::Version
|
180
208
|
version: '0'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: yard
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
181
223
|
description:
|
182
224
|
email:
|
183
225
|
- jonas.nicklas@gmail.com
|
@@ -298,3 +340,4 @@ test_files:
|
|
298
340
|
- spec/refile/test_app/config/routes.rb
|
299
341
|
- spec/refile/test_app/public/favicon.ico
|
300
342
|
- spec/refile_spec.rb
|
343
|
+
has_rdoc:
|