fakerclip 0.0.2 → 0.1.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.
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