fakerclip 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -34,6 +34,8 @@ gem 'fakerclip'
34
34
 
35
35
  That's it! Now, just omit `: { path: 'is/my/local/path' }` from the example above and expect that your files will appear in `"#{Rails.root}/public/fakerclip/(development|test)/s3-foo-bar-bucket/"` with the same structure as you would expect on S3, e.g. `is/my/s3/path` from above.
36
36
 
37
+ You can use either/both the fog and the aws-sdk gems as the client for S3
38
+
37
39
  ### Development
38
40
 
39
41
  ``` shell
@@ -2,6 +2,9 @@ module Fakerclip
2
2
 
3
3
  class Reads
4
4
 
5
+ SUBDOMAIN_BUCKET_REGEX = %r{https?:\/\/(.+)\.s3\.amazonaws\.com}
6
+ PATH_BUCKET_REGEX = %r{https?:\/\/s3\.amazonaws\.com\/([^\/]+)\/}
7
+
5
8
  def self.activate
6
9
  Paperclip::Attachment.default_options[:url_generator] = UrlGenerator
7
10
  end
@@ -11,9 +14,11 @@ module Fakerclip
11
14
  def for(style_name, options)
12
15
  uri = URI.parse(super)
13
16
 
14
- if uri.to_s.match(/\.s3\.amazonaws\.com/)
15
- bucket = uri.host.split(/\./, 2).first
16
- "/fake_s3_#{Rails.env}/#{bucket}#{uri.request_uri}"
17
+ case uri.to_s
18
+ when SUBDOMAIN_BUCKET_REGEX
19
+ "/fake_s3_#{Rails.env}/#{$1}#{uri.request_uri}"
20
+ when PATH_BUCKET_REGEX
21
+ "/fake_s3_#{Rails.env}#{uri.request_uri}"
17
22
  else
18
23
  uri.to_s
19
24
  end
@@ -1,3 +1,3 @@
1
1
  module Fakerclip
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,36 +1,87 @@
1
1
  module Fakerclip
2
2
 
3
+ # TODO: * set mocking for Excon to only apply to *some-bucket*.s3.amazonaws.com and only
4
+ # while paperclip is making the requests, so we don't clobber other legit requests.
3
5
  class Writes
4
6
 
5
7
  def self.activate
6
- # stubbing writes to S3
7
- ::Excon.stub({ method: "PUT" }) do |params|
8
+ # fog gem support
9
+ ::Excon.stub({ method: "PUT" }, FakeS3::ExconResponder.block)
10
+ ::Excon.defaults[:mock] = true
8
11
 
9
- # TODO: generate etags for multipart uploads
10
- etag = Digest::MD5.hexdigest(params[:body])
12
+ # aws-sdk gem support
13
+ Artifice.activate_with(FakeS3::AWSSDKResponder.new)
14
+ end
11
15
 
12
- s3_bucket = params[:host].split('.').first
13
- s3_file_path = CGI.unescape params[:path]
14
- local_s3_path = Rails.root.join(File.join('public', "fake_s3_#{Rails.env}"))
15
- local_file_path = File.join(local_s3_path, s3_bucket, s3_file_path)
16
+ class S3Request
16
17
 
17
- # creates the file tree, e.g. public/fake_s3_development/s3-bucket/files/1/
18
- FileUtils.mkdir_p File.dirname(local_file_path)
18
+ attr_accessor :body, :etag, :s3_path, :s3_bucket
19
19
 
20
- # writes the file to the fake s3
21
- File.open(local_file_path, "wb") {|file| file.write(params[:body]) }
22
-
23
- # TODO: generate alternate statuses, e.g. if the file is not found
24
- {
25
- status: 200,
26
- headers: params[:headers].merge("ETag" => etag),
27
- body: params[:body]
28
- }
20
+ def initialize(env)
21
+ self.body = env['rack.input'] && env['rack.input'].read || env[:body]
22
+ self.s3_bucket = (env['HTTP_HOST'] || env[:host]).split('.').first
23
+ self.s3_path = env['PATH_INFO'] || CGI.unescape(env[:path])
24
+ self.etag = Digest::MD5::hexdigest(body)
29
25
  end
26
+ end
30
27
 
31
- # TODO: set mocking for Excon to apply only to some-bucket.s3.amazonaws.com and only
32
- # while paperclip is making the requests, so we don't clobber other legit requests.
33
- ::Excon.defaults[:mock] = true
28
+ class FakeS3
29
+
30
+ class AWSSDKResponder
31
+
32
+ def call(env)
33
+ Response.new(env).to_hash.values
34
+ end
35
+ end
36
+
37
+ class ExconResponder
38
+
39
+ def self.block
40
+ Proc.new { |env| Response.new(env).to_hash }
41
+ end
42
+ end
43
+
44
+ class Response
45
+
46
+ def initialize(env)
47
+ @request = S3Request.new(env)
48
+
49
+ LocalS3Object.new(@request.s3_bucket, @request.s3_path).save(@request.body)
50
+ end
51
+
52
+ def to_hash
53
+ # TODO: generate etags for multipart uploads
54
+ {
55
+ status: 200,
56
+ headers: { "ETag" => @request.etag },
57
+ body: ["OK"]
58
+ }
59
+ end
60
+ end
61
+
62
+ class LocalS3Object
63
+
64
+ def initialize(s3_bucket, s3_file_path)
65
+ @local_file_path = File.join(path_to_local_s3, s3_bucket, s3_file_path)
66
+
67
+ ensure_path_exists
68
+ end
69
+
70
+ # writes the file to the fake s3
71
+ def save(data)
72
+ File.open(@local_file_path, "wb") {|file| file.write(data) }
73
+ end
74
+
75
+ private
76
+
77
+ def path_to_local_s3
78
+ Rails.root.join(File.join('public', "fake_s3_#{Rails.env}"))
79
+ end
80
+
81
+ def ensure_path_exists
82
+ FileUtils.mkdir_p File.dirname(@local_file_path)
83
+ end
84
+ end
34
85
  end
35
86
  end
36
87
  end
data/lib/fakerclip.rb CHANGED
@@ -1,6 +1,8 @@
1
+ # TODO: move these where they are needed
1
2
  require 'fileutils'
2
3
  require 'paperclip'
3
4
  require 'fog'
5
+ require 'artifice'
4
6
 
5
7
  module Fakerclip
6
8
 
@@ -0,0 +1,14 @@
1
+ class AwsSdkS3GemUpload < Upload
2
+
3
+ has_attached_file :file,
4
+ :storage => :s3,
5
+ :s3_credentials => {
6
+ :access_key_id => "AWSACCESSKEY",
7
+ :secret_access_key => "AWSSECRETKEY"
8
+ },
9
+ :bucket => "some-bucket",
10
+ :s3_permissions => :public_read,
11
+ :path => ":attachment/:id/:basename.:extension"
12
+
13
+ before_post_process :image?
14
+ end
@@ -0,0 +1,15 @@
1
+ class FogS3GemUpload < Upload
2
+
3
+ has_attached_file :file,
4
+ :storage => :fog,
5
+ :fog_public => true,
6
+ :fog_credentials => {
7
+ :provider => 'AWS',
8
+ :aws_access_key_id => "AWSACCESSKEY",
9
+ :aws_secret_access_key => "AWSSECRETKEY"
10
+ },
11
+ :fog_directory => "some-bucket",
12
+ :path => ":attachment/:id/:basename.:extension"
13
+
14
+ before_post_process :image?
15
+ end
@@ -2,18 +2,6 @@ class Upload < ActiveRecord::Base
2
2
 
3
3
  attr_accessible :file
4
4
 
5
- has_attached_file :file,
6
- :storage => :fog,
7
- :fog_public => true,
8
- :fog_credentials => {
9
- :provider => 'AWS',
10
- :aws_access_key_id => "AWSACCESSKEY",
11
- :aws_secret_access_key => "AWSSECRETKEY"
12
- },
13
- :fog_directory => "some-bucket",
14
- :path => ":attachment/:id/:basename.:extension"
15
-
16
- before_post_process :image?
17
5
  def image?
18
6
  false
19
7
  end
Binary file