file_column_with_s3 0.1.1 → 0.1.2

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/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- require 'bundler'
1
+ require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
4
  task :default => [:test]
@@ -31,8 +31,8 @@ task :package => [:checkout_release, :release_docs] do
31
31
  sh "cd release; tar czf #{PKG_NAME}-#{PKG_VERSION}.tar.gz #{PKG_NAME}-#{PKG_VERSION}"
32
32
  end
33
33
 
34
+ desc "Run all tests"
34
35
  task :test do
35
- sh "cd test; ruby attachement_store_test.rb"
36
36
  sh "cd test; ruby file_column_test.rb"
37
37
  sh "cd test; ruby file_column_helper_test.rb"
38
38
  sh "cd test; ruby magick_test.rb"
data/lib/file_column.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'fileutils'
2
2
  require 'tempfile'
3
3
  require 'magick_file_column'
4
- require 'file_column/attachement_store'
4
+ require 'storage'
5
5
 
6
6
  module FileColumn # :nodoc:
7
7
  def self.append_features(base)
@@ -18,20 +18,22 @@ module FileColumn # :nodoc:
18
18
  end
19
19
  end
20
20
 
21
- #todo: dir is not required for all type of store
22
- def self.store(dir)
23
- (@store_builder || AttachementStore::Builder.new(:filesystem)).build(dir)
21
+ def self.store(path_prefix, extra_opts={})
22
+ builder = @store_builder || Storage::Builder.new(:filesystem)
23
+ @build_opts ||= {}
24
+ builder.build(path_prefix, @build_opts.merge(extra_opts))
24
25
  end
25
26
 
26
- def self.store=(args)
27
- @store_builder = AttachementStore::Builder.new(*args)
27
+ def self.config_store(type, build_opts={})
28
+ @build_opts = build_opts
29
+ @store_builder = Storage::Builder.new(type)
28
30
  end
29
31
 
30
32
  def self.init_options(defaults, model, attr)
31
33
  options = defaults.dup
32
- options[:store_dir] ||= File.join(options[:root_path], model, attr)
34
+ options[:store_dir] ||= File.join(model, attr)
33
35
  unless options[:store_dir].is_a?(Symbol)
34
- options[:tmp_base_dir] ||= File.join(options[:store_dir], "tmp")
36
+ options[:tmp_base_dir] ||= File.join(options[:root_path], options[:store_dir], "tmp")
35
37
  end
36
38
  options[:base_url] ||= options[:web_root] + File.join(model, attr)
37
39
 
@@ -51,6 +53,9 @@ module FileColumn # :nodoc:
51
53
  @options_method = "#{attr}_options".to_sym
52
54
  end
53
55
 
56
+ def store
57
+ nil
58
+ end
54
59
 
55
60
  def assign(file)
56
61
  if file.is_a? File
@@ -122,10 +127,7 @@ module FileColumn # :nodoc:
122
127
  def store_dir
123
128
  if options[:store_dir].is_a? Symbol
124
129
  raise ArgumentError.new("'#{options[:store_dir]}' is not an instance method of class #{@instance.class.name}") unless @instance.respond_to?(options[:store_dir])
125
-
126
- dir = File.join(options[:root_path], @instance.send(options[:store_dir]))
127
- FileUtils.mkpath(dir) unless File.exists?(dir)
128
- dir
130
+ @instance.send(options[:store_dir])
129
131
  else
130
132
  options[:store_dir]
131
133
  end
@@ -135,7 +137,7 @@ module FileColumn # :nodoc:
135
137
  if options[:tmp_base_dir]
136
138
  options[:tmp_base_dir]
137
139
  else
138
- dir = File.join(store_dir, "tmp")
140
+ dir = File.join(options[:root_path], store_dir, "tmp")
139
141
  FileUtils.mkpath(dir) unless File.exists?(dir)
140
142
  dir
141
143
  end
@@ -223,7 +225,8 @@ module FileColumn # :nodoc:
223
225
  def store_upload(file)
224
226
  @tmp_dir = FileColumn.generate_temp_name
225
227
  @dir = File.join(tmp_base_dir, @tmp_dir)
226
- FileUtils.mkdir(@dir)
228
+
229
+ FileUtils.mkdir_p(@dir)
227
230
 
228
231
  @filename = FileColumn::sanitize_filename(file.original_filename)
229
232
  local_file_path = File.join(tmp_base_dir,@tmp_dir,@filename)
@@ -356,22 +359,24 @@ module FileColumn # :nodoc:
356
359
  class PermanentUploadedFile < RealUploadedFile # :nodoc:
357
360
  def initialize(*args)
358
361
  super *args
359
- @store = FileColumn.store(store_dir)
360
362
  @filename = @instance[@attr]
361
363
  @filename = nil if @filename.empty?
362
364
  end
363
365
 
366
+ def store
367
+ FileColumn.store(store_dir, {:root_path => options[:root_path] }) #root_path is only need for file system store, but pass it in will not hurt for other store
368
+ end
369
+
364
370
  def absolute_path(subdir=nil)
365
371
  if subdir
366
- @store.absolute_path(File.join(relative_path_prefix, subdir, @filename))
372
+ store.absolute_path(File.join(relative_path_prefix, subdir, @filename))
367
373
  else
368
- @store.absolute_path(File.join(relative_path_prefix, @filename))
374
+ store.absolute_path(File.join(relative_path_prefix, @filename))
369
375
  end
370
376
  end
371
377
 
372
378
  def move_from(local_dir, just_uploaded)
373
- @store.upload_dir(relative_path_prefix, local_dir)
374
-
379
+ store.upload_dir(relative_path_prefix, local_dir)
375
380
  @just_uploaded = just_uploaded
376
381
  end
377
382
 
@@ -390,7 +395,6 @@ module FileColumn # :nodoc:
390
395
 
391
396
  def assign_temp(temp_path)
392
397
  return nil if temp_path.nil? or temp_path.empty?
393
-
394
398
  temp = clone_as TempUploadedFile
395
399
  temp.parse_temp_path(temp_path)
396
400
  temp
@@ -401,7 +405,7 @@ module FileColumn # :nodoc:
401
405
  end
402
406
 
403
407
  def delete_files
404
- @store.clear
408
+ store.delete(relative_path_prefix)
405
409
  end
406
410
 
407
411
  private
@@ -541,7 +545,7 @@ module FileColumn # :nodoc:
541
545
  #
542
546
  # For setting a static storage_dir that doesn't change with respect to a particular
543
547
  # instance, you assign <tt>:storage_dir</tt> a String representing a directory
544
- # as an absolute path.
548
+ # as a relative path under root_path.
545
549
  #
546
550
  # If you need more fine-grained control over the storage directory, you
547
551
  # can use the name of a callback-method as a symbol for the
@@ -642,13 +646,13 @@ module FileColumn # :nodoc:
642
646
  result
643
647
  end
644
648
 
649
+ private state_method
650
+
645
651
  define_method "file_column_relative_path_prefix" do
646
652
  raise RuntimeError.new("Trying to access file_column, but primary key got lost.") if self.id.to_s.empty?
647
- File.join(*("%08d" % self.id).scan(/..../))
653
+ options[:use_safe_path] ? File.join(*("%08d" % self.id).scan(/..../)) : self.id.to_s
648
654
  end
649
655
 
650
- private state_method
651
-
652
656
  define_method attr do |*args|
653
657
  send(state_method).absolute_path *args
654
658
  end
@@ -702,6 +706,7 @@ module FileColumn # :nodoc:
702
706
  send(state_method).just_uploaded?
703
707
  end
704
708
 
709
+
705
710
  # this creates a closure keeping a reference to my_options
706
711
  # right now that's the only way we store the options. We
707
712
  # might use a class attribute as well
@@ -709,6 +714,30 @@ module FileColumn # :nodoc:
709
714
  my_options
710
715
  end
711
716
 
717
+ define_method "#{attr}_download_url" do |context_path, *args|
718
+ state = send(state_method)
719
+ relative_path = state.relative_path(*args)
720
+ return nil unless relative_path
721
+
722
+ store = state.store
723
+ return store.url_for(relative_path) if store && store.respond_to?(:url_for)
724
+
725
+ url = ""
726
+ url << context_path if context_path
727
+ url << "/"
728
+ url << state.options[:base_url] << "/"
729
+ url << relative_path
730
+ end
731
+
732
+ define_method "#{attr}_copy_to" do |local_path, *args|
733
+ state = send(state_method)
734
+ relative_path = state.relative_path(*args)
735
+ return nil unless relative_path
736
+ store = state.store
737
+ FileUtils.mkdir_p(File.dirname(local_path))
738
+ store.copy(relative_path, local_path)
739
+ end
740
+
712
741
  private after_save_method, after_destroy_method
713
742
 
714
743
  FileColumn::MagickExtension::file_column(self, attr, my_options) if options[:magick]
@@ -725,7 +754,8 @@ module FileColumn # :nodoc:
725
754
 
726
755
  def self.sanitize_filename(filename)
727
756
  filename = File.basename(filename.gsub("\\", "/")) # work-around for IE
728
- filename.gsub!(/[^a-zA-Z0-9\.\-\+_]/,"_")
757
+ # cannot use \w or \W since Rails enables unicode $KCODE flag
758
+ filename.gsub!(/[^A-Za-z0-9_\-\.]/, "_")
729
759
  filename = "_#{filename}" if filename =~ /^\.+$/
730
760
  filename = "unnamed" if filename.size == 0
731
761
  filename
@@ -3,7 +3,7 @@
3
3
  # automatically included into ActionView::Base, thereby making this module's
4
4
  # methods available in all your views.
5
5
  module FileColumnHelper
6
-
6
+
7
7
  # Use this helper to create an upload field for a file_column attribute. This will generate
8
8
  # an additional hidden field to keep uploaded files during form-redisplays. For example,
9
9
  # when called with
@@ -26,7 +26,7 @@ module FileColumnHelper
26
26
  result = ActionView::Helpers::InstanceTag.new(object.dup, method.to_s+"_temp", self).to_input_field_tag("hidden", {})
27
27
  result << ActionView::Helpers::InstanceTag.new(object.dup, method, self).to_input_field_tag("file", options)
28
28
  end
29
-
29
+
30
30
  # Creates an URL where an uploaded file can be accessed. When called for an Entry object with
31
31
  # id 42 (stored in <tt>@entry</tt>) like this
32
32
  #
@@ -71,15 +71,10 @@ module FileColumnHelper
71
71
  subdir = options
72
72
  end
73
73
  end
74
-
75
- relative_path = object.send("#{method}_relative_path", subdir)
76
- return nil unless relative_path
77
74
 
78
- url = ""
79
- url << ActionController::Base.relative_url_root.to_s if absolute
80
- url << "/"
81
- url << object.send("#{method}_options")[:base_url] << "/"
82
- url << relative_path
75
+ context_path = absolute ? ActionController::Base.relative_url_root.to_s : nil
76
+ object.send("#{method}_download_url", context_path, subdir)
77
+
83
78
  end
84
79
 
85
80
  # Same as +url_for_file_colum+ but allows you to access different versions
@@ -115,7 +110,7 @@ module FileColumnHelper
115
110
  #
116
111
  # and
117
112
  #
118
- # <%= url_for_image_column @entry, "image",
113
+ # <%= url_for_image_column @entry, "image",
119
114
  # :size => "50x50", :crop => "1:1", :name => "thumb" %>
120
115
  #
121
116
  # will produce something like this:
@@ -17,7 +17,7 @@ module FileColumn # :nodoc:
17
17
  options[:magick][:versions].each_pair do |version, version_options|
18
18
  next if version_options[:lazy]
19
19
  dirname = version_options[:name]
20
- FileUtils.mkdir File.join(@dir, dirname)
20
+ FileUtils.mkdir_p File.join(@dir, dirname)
21
21
  transform_image(img, version_options, absolute_path(dirname))
22
22
  end
23
23
  end
@@ -55,7 +55,7 @@ module FileColumn # :nodoc:
55
55
  return nil
56
56
  end
57
57
  dirname = version_options[:name]
58
- FileUtils.mkdir File.join(@dir, dirname)
58
+ FileUtils.mkdir_p File.join(@dir, dirname)
59
59
  transform_image(img, version_options, absolute_path(dirname))
60
60
  end
61
61
 
data/s3_env.example CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/bin/sh
2
2
 
3
- export S3_ACCESS_KEY_ID=<key-id>
4
- export S3_SECRET_ACCESS_KEY=<access-key>
3
+ export AWS_ACCESS_KEY_ID=<key-id>
4
+ export AWS_SECRET_ACCESS_KEY=<access-key>
5
5
  export S3_BUCKET_NAME=file-column-attachement-test
@@ -64,3 +64,39 @@ class Test::Unit::TestCase
64
64
 
65
65
  alias_method :f, :file_path
66
66
  end
67
+
68
+ # provid a dummy storage implementation for tests
69
+
70
+ class InMemoryWithUrlStorageStore
71
+ def initialize(path_prefix, options)
72
+ @path_prefix = path_prefix
73
+ @storage = {}
74
+ end
75
+ def upload(path, file)
76
+ @storage[absolute_path(path) + "/" + File.basename(file)] = File.read(file)
77
+ end
78
+
79
+ def upload_dir(path, local_dir)
80
+ Dir[File.join(local_dir, "*")].each do |f|
81
+ upload(path, f)
82
+ end
83
+ end
84
+
85
+ def exists?(path)
86
+ File.key?(path)
87
+ end
88
+
89
+ def url_for(path)
90
+ "store generated url for #{path}"
91
+ end
92
+
93
+ def absolute_path(path)
94
+ File.join(@path_prefix, path)
95
+ end
96
+
97
+ def clear
98
+ @storage = {}
99
+ end
100
+ end
101
+
102
+ Storage.add_store_class(:in_memory_with_url, InMemoryWithUrlStorageStore)
@@ -6,9 +6,19 @@ class UrlForFileColumnTest < Test::Unit::TestCase
6
6
 
7
7
  def setup
8
8
  Entry.file_column :image
9
+ ActionController::Base.relative_url_root = nil
9
10
  @request = RequestMock.new
10
11
  end
11
12
 
13
+ def test_should_use_store_generated_url_if_file_store_configured_can_do_it
14
+ FileColumn.config_store(:in_memory_with_url)
15
+ @e = Entry.new(:image => upload(f("skanthak.png")))
16
+ assert @e.save
17
+ assert_equal "store generated url for #{@e.image_relative_path}", url_for_file_column("e", "image")
18
+ ensure
19
+ FileColumn.config_store(:filesystem)
20
+ end
21
+
12
22
  def test_url_for_file_column_with_temp_entry
13
23
  @e = Entry.new(:image => upload(f("skanthak.png")))
14
24
  url = url_for_file_column("e", "image")
@@ -26,7 +36,6 @@ class UrlForFileColumnTest < Test::Unit::TestCase
26
36
  def test_url_for_file_column_works_with_symbol
27
37
  @e = Entry.new(:image => upload(f("skanthak.png")))
28
38
  assert @e.save
29
-
30
39
  url = url_for_file_column(:e, :image)
31
40
  assert_equal "/entry/image/#{@e.file_column_relative_path_prefix}/skanthak.png", url
32
41
  end
@@ -52,7 +61,7 @@ class UrlForFileColumnTest < Test::Unit::TestCase
52
61
  end
53
62
  end
54
63
 
55
- class UrlForFileColumnTest < Test::Unit::TestCase
64
+ class UrlForFileColumnWithContextPathTest < Test::Unit::TestCase
56
65
  include FileColumnHelper
57
66
  include ActionView::Helpers::AssetTagHelper
58
67
  include ActionView::Helpers::TagHelper
@@ -75,7 +84,8 @@ class UrlForFileColumnTest < Test::Unit::TestCase
75
84
  def test_with_image_tag
76
85
  e = Entry.new(:image => upload(f("skanthak.png")))
77
86
  html = image_tag url_for_file_column(e, "image")
78
- url = html.scan(/src=\"(.+)\?.*\"/).first.first
87
+
88
+ url = html.scan(/src=\"([^?]+)\?*.*\"/).first.first
79
89
 
80
90
  assert_match IMAGE_URL, url
81
91
  end
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require File.dirname(__FILE__) + '/abstract_unit'
2
3
 
3
4
  require File.dirname(__FILE__) + '/fixtures/entry'
@@ -39,12 +40,14 @@ class FileColumnTest < Test::Unit::TestCase
39
40
  assert_equal "__foo", FileColumn::sanitize_filename('`*foo')
40
41
  assert_equal "foo.txt", FileColumn::sanitize_filename('c:\temp\foo.txt')
41
42
  assert_equal "_.", FileColumn::sanitize_filename(".")
43
+ assert_equal "a_b.jpg", FileColumn::sanitize_filename("a+b.jpg")
42
44
  end
43
45
 
46
+
44
47
  def test_default_options
45
48
  e = Entry.new
46
- assert_match %r{/public/entry/image}, e.image_options[:store_dir]
47
- assert_match %r{/public/entry/image/tmp}, e.image_options[:tmp_base_dir]
49
+ assert_match %r{entry/image}, e.image_options[:store_dir]
50
+ assert_match %r{entry/image/tmp}, e.image_options[:tmp_base_dir]
48
51
  end
49
52
 
50
53
  def test_assign_without_save_with_tempfile
@@ -582,6 +585,13 @@ class FileColumnTest < Test::Unit::TestCase
582
585
  e["id"] = nil
583
586
  assert_raise(RuntimeError) { e.image }
584
587
  end
588
+
589
+ def test_copy_file_to_local_dir
590
+ e = Entry.new(:image => upload(f("skanthak.png")))
591
+ assert e.save
592
+ e.image_copy_to('/tmp/file_column_test/copy_dir/skanthak.png')
593
+ assert File.exist?('/tmp/file_column_test/copy_dir/skanthak.png')
594
+ end
585
595
  end
586
596
 
587
597
  # Tests for moving temp dir to permanent dir
@@ -650,3 +660,43 @@ class FileColumnMoveTest < Test::Unit::TestCase
650
660
  end
651
661
 
652
662
  end
663
+
664
+
665
+ # Tests for moving temp dir to permanent dir
666
+ class FileColumnDownloadUrlTest < Test::Unit::TestCase
667
+
668
+
669
+ def test_default_download_url_is_relative
670
+ Entry.file_column :image
671
+ e = Entry.new(:image => upload(f("skanthak.png")))
672
+ assert e.save
673
+
674
+ assert_equal "/entry/image/#{e.id}/skanthak.png", e.image_download_url(nil)
675
+ end
676
+
677
+ def test_download_url_with_specified_url_base
678
+ Entry.file_column :image, :base_url => 'foo'
679
+ e = Entry.new(:image => upload(f("skanthak.png")))
680
+ assert e.save
681
+
682
+ assert_equal "/foo/#{e.id}/skanthak.png", e.image_download_url(nil)
683
+ end
684
+
685
+ def test_download_url_with_specified_subdir
686
+ Entry.file_column :image
687
+ e = Entry.new(:image => upload(f("skanthak.png")))
688
+ assert e.save
689
+
690
+ assert_equal "/entry/image/#{e.id}/foo/skanthak.png", e.image_download_url(nil, 'foo')
691
+ end
692
+
693
+
694
+ def test_should_use_store_generated_url_if_storage_configured_can_do_it
695
+ FileColumn.config_store(:in_memory_with_url)
696
+ e = Entry.new(:image => upload(f("skanthak.png")))
697
+ assert e.save
698
+ assert_equal "store generated url for #{e.image_relative_path}", e.image_download_url(nil)
699
+ ensure
700
+ FileColumn.config_store(:filesystem)
701
+ end
702
+ end
data/test/magick_test.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  begin
2
- require 'RMagick'
3
2
  require File.dirname(__FILE__) + '/abstract_unit'
4
3
  require File.dirname(__FILE__) + '/fixtures/entry'
5
4
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file_column_with_s3
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Mingle SaaS team
@@ -15,13 +15,31 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-09-20 00:00:00 Z
18
+ date: 2013-08-19 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- version_requirements: &id001 !ruby/object:Gem::Requirement
21
+ name: mingle-storage
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 29
29
+ segments:
30
+ - 0
31
+ - 0
32
+ - 1
33
+ version: 0.0.1
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rails
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
22
40
  none: false
23
41
  requirements:
24
- - - "="
42
+ - - ~>
25
43
  - !ruby/object:Gem::Version
26
44
  hash: 19
27
45
  segments:
@@ -29,12 +47,12 @@ dependencies:
29
47
  - 3
30
48
  - 8
31
49
  version: 2.3.8
32
- prerelease: false
33
50
  type: :runtime
34
- name: rails
35
- requirement: *id001
51
+ version_requirements: *id002
36
52
  - !ruby/object:Gem::Dependency
37
- version_requirements: &id002 !ruby/object:Gem::Requirement
53
+ name: sqlite3
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
38
56
  none: false
39
57
  requirements:
40
58
  - - ">="
@@ -43,12 +61,12 @@ dependencies:
43
61
  segments:
44
62
  - 0
45
63
  version: "0"
46
- prerelease: false
47
64
  type: :development
48
- name: sqlite3
49
- requirement: *id002
65
+ version_requirements: *id003
50
66
  - !ruby/object:Gem::Dependency
51
- version_requirements: &id003 !ruby/object:Gem::Requirement
67
+ name: rmagick
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
52
70
  none: false
53
71
  requirements:
54
72
  - - ">="
@@ -57,10 +75,22 @@ dependencies:
57
75
  segments:
58
76
  - 0
59
77
  version: "0"
78
+ type: :development
79
+ version_requirements: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ name: aws-sdk
60
82
  prerelease: false
83
+ requirement: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
61
92
  type: :development
62
- name: rmagick
63
- requirement: *id003
93
+ version_requirements: *id005
64
94
  description:
65
95
  email: mingle.saas@thoughtworks.com
66
96
  executables: []
@@ -71,7 +101,6 @@ extra_rdoc_files: []
71
101
 
72
102
  files:
73
103
  - Rakefile
74
- - lib/file_column/attachement_store.rb
75
104
  - lib/file_column.rb
76
105
  - lib/file_column_helper.rb
77
106
  - lib/file_compat.rb
@@ -80,7 +109,6 @@ files:
80
109
  - lib/test_case.rb
81
110
  - lib/validations.rb
82
111
  - test/abstract_unit.rb
83
- - test/attachement_store_test.rb
84
112
  - test/connection.rb
85
113
  - test/file_column_helper_test.rb
86
114
  - test/file_column_test.rb
@@ -124,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
152
  requirements: []
125
153
 
126
154
  rubyforge_project:
127
- rubygems_version: 1.8.24
155
+ rubygems_version: 1.8.25
128
156
  signing_key:
129
157
  specification_version: 3
130
158
  summary: File attachment library for ruby
@@ -1,93 +0,0 @@
1
- module FileColumn
2
- module AttachementStore
3
- begin
4
- require 'aws-sdk'
5
- class S3Store
6
- def initialize(options)
7
- s3 = AWS::S3.new(:access_key_id => options[:access_key_id],
8
- :secret_access_key => options[:secret_access_key])
9
- @bucket = s3.buckets[options[:bucket_name]]
10
- end
11
-
12
- def upload(path, local_file)
13
- @bucket.objects.create('/' + path + "/" + File.basename(local_file), File.read(local_file))
14
- end
15
-
16
- def upload_dir(path, local_dir)
17
- @bucket.objects.with_prefix("/" + path).delete_all
18
- Dir[File.join(local_dir, "*")].each do |f|
19
- upload(path, f)
20
- end
21
- end
22
-
23
- def read(path)
24
- @bucket.objects["/" + path ].read
25
- end
26
-
27
- def exists?(path)
28
- @bucket.objects['/' + path].exists?
29
- end
30
-
31
- def clear
32
- @bucket.clear!
33
- end
34
- end
35
- rescue LoadError => e
36
- puts "Warning: can not load aws-sdk gem, s3 file store disabled"
37
- end
38
-
39
- class FilesystemStore
40
- def initialize(dir)
41
- @dir = dir
42
- FileUtils.mkdir_p @dir
43
- end
44
-
45
- def read(path)
46
- File.read(absolute_path(path))
47
- end
48
-
49
- def upload(path, local_file)
50
- FileUtils.mkdir_p(absolute_path(path))
51
- FileUtils.mv(local_file, absolute_path(path))
52
- end
53
-
54
- def upload_dir(path, local_dir)
55
- FileUtils.rm_rf(absolute_path(path))
56
- Dir[File.join(local_dir, "*")].each do |f|
57
- upload(path, f)
58
- end
59
- end
60
-
61
- #todo: this should be interface that retrive a lazy file object
62
- def absolute_path(*relative_paths)
63
- File.join(@dir, *relative_paths)
64
- end
65
-
66
- def exists?(file_path)
67
- File.exists?(absolute_path(file_path))
68
- end
69
-
70
- def clear
71
- FileUtils.rm_rf @dir
72
- end
73
- end
74
-
75
- class Builder
76
- def initialize(*build_opts)
77
- @type, *@build_opts = *build_opts
78
- end
79
-
80
- def build(dir=nil)
81
- args = @build_opts
82
- args += [dir] if @type == :filesystem
83
- store_class.new(*args)
84
- end
85
-
86
- private
87
-
88
- def store_class
89
- ActiveSupport::Inflector.constantize("FileColumn::AttachementStore::#{ActiveSupport::Inflector.camelize(@type)}Store")
90
- end
91
- end
92
- end
93
- end
@@ -1,96 +0,0 @@
1
- require File.dirname(__FILE__) + '/abstract_unit'
2
- require 'active_support/test_case'
3
-
4
- class AttachementStoreTest < Test::Unit::TestCase
5
- extend Test::Unit::Assertions
6
-
7
- STORE_DIR = File.dirname(__FILE__)+"/public/entry"
8
- STORE_BUILD_OPTS = [[:filesystem]]
9
- if !ENV["S3_ACCESS_KEY_ID"].blank?
10
- STORE_BUILD_OPTS << [:s3, {
11
- :access_key_id => ENV["S3_ACCESS_KEY_ID"],
12
- :secret_access_key => ENV["S3_SECRET_ACCESS_KEY"],
13
- :bucket_name => ENV["S3_BUCKET_NAME"]}]
14
- end
15
-
16
- def teardown
17
- FileColumn.store(STORE_DIR).clear
18
- FileUtils.rm_rf("/tmp/file_column_test")
19
- end
20
-
21
- def self.store_test(test_name, store_type, *store_building_args, &block)
22
- define_method(test_name + "_for_#{store_type}_store") do
23
- FileColumn.store = store_type, *store_building_args
24
- yield
25
- end
26
- end
27
-
28
-
29
- STORE_BUILD_OPTS.each do |store_type, *rest_args|
30
- store_test "test_build_right_store", store_type, *rest_args do
31
- assert FileColumn.store("/tmp/attachements").class.name.include?(ActiveSupport::Inflector.camelize(store_type))
32
- end
33
-
34
- store_test "test_upload_local_file", store_type, *rest_args do
35
- file = "/tmp/file_column_test/abc"
36
- FileUtils.mkdir_p(File.dirname(file))
37
- FileUtils.touch(file)
38
- store = FileColumn.store(STORE_DIR)
39
- store.upload("x/y/z", file)
40
- assert !store.exists?("x/abc")
41
- assert store.exists?("x/y/z/abc")
42
- assert_equal "", store.read("x/y/z/abc")
43
- end
44
-
45
- store_test "test_upload_with_same_name_replace_file", store_type, *rest_args do
46
- file = "/tmp/file_column_test/abc"
47
- FileUtils.mkdir_p(File.dirname(file))
48
- File.open(file, "w+") { |f| f << "123" }
49
-
50
- store = FileColumn.store(STORE_DIR)
51
- store.upload("x/y/z", file)
52
-
53
- assert_equal "123", store.read("x/y/z/abc")
54
-
55
- File.open(file, "w+") { |f| f << "456" }
56
- store.upload("x/y/z", file)
57
-
58
- assert_equal "456", store.read("x/y/z/abc")
59
- end
60
-
61
- store_test "test_upload_local_dir", store_type, *rest_args do
62
- local_dir = "/tmp/file_column_test"
63
- FileUtils.mkdir_p(local_dir)
64
- FileUtils.touch(File.join(local_dir, "a"))
65
- FileUtils.touch(File.join(local_dir, "b"))
66
-
67
- store = FileColumn.store(STORE_DIR)
68
- store.upload_dir("x/y/z", local_dir)
69
-
70
- assert store.exists?("x/y/z/a")
71
- assert store.exists?("x/y/z/b")
72
- end
73
-
74
-
75
- store_test "test_upload_local_dir_with_replace_files", store_type, *rest_args do
76
-
77
- local_dir = "/tmp/file_column_test/old"
78
- FileUtils.mkdir_p(local_dir)
79
- FileUtils.touch(File.join(local_dir, "a"))
80
-
81
- store = FileColumn.store(STORE_DIR)
82
- store.upload_dir("x/y/z", local_dir)
83
-
84
- local_dir = "/tmp/file_column_test/new"
85
- FileUtils.mkdir_p(local_dir)
86
- FileUtils.touch(File.join(local_dir, "b"))
87
-
88
- store = FileColumn.store(STORE_DIR)
89
- store.upload_dir("x/y/z", local_dir)
90
-
91
- assert store.exists?("x/y/z/b")
92
- assert !store.exists?("x/y/z/a")
93
- end
94
-
95
- end
96
- end