jsl-archived_attributes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require 'rake'
5
+ require 'spec/rake/spectask'
6
+ require 'rake/rdoctask'
7
+
8
+ desc 'Test the plugin.'
9
+ Spec::Rake::SpecTask.new(:spec) do |t|
10
+ t.spec_opts = ["--format", "specdoc", "--colour"]
11
+ t.libs << 'lib'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc "Run all the tests"
16
+ task :default => :spec
17
+
18
+ desc 'Generate documentation for the compressed_attributes plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'ArchivedAttributes'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
@@ -0,0 +1,30 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "archived_attributes"
3
+ s.version = "0.0.1"
4
+ s.date = "2009-01-25"
5
+ s.summary = "Rails plugin to save content to a pluggable back-end"
6
+ s.email = "justin@phq.org"
7
+ s.homepage = "http://github.com/jsl/archived_attributes"
8
+ s.description = "ArchivedAttributes allows for data to be saved to a backend other than the rdbms"
9
+ s.has_rdoc = true
10
+ s.authors = ["Justin Leitgeb"]
11
+ s.files = [
12
+ "Rakefile",
13
+ "archived_attributes.gemspec",
14
+ "init.rb",
15
+ "config/archived_attributes.yml",
16
+ "lib/archived_attributes.rb",
17
+ "lib/archived_attributes/archived_attribute.rb",
18
+ "lib/archived_attributes/global_configuration.rb",
19
+ "lib/archived_attributes/backends/s3.rb",
20
+ "lib/archived_attributes/backends/filesystem.rb"
21
+ ]
22
+ s.test_files = [
23
+ "spec/archived_attributes/global_configuration_spec.rb",
24
+ "spec/archived_attributes/archived_attribute_spec.rb",
25
+ "spec/archived_attributes/backends/filesystem_spec.rb",
26
+ "spec/archived_attributes/backends/s3_spec.rb"
27
+ ]
28
+ s.add_dependency("right_aws", ["> 0.0.0"])
29
+ s.add_dependency("assaf-uuid", ["> 0.0.0"])
30
+ end
@@ -0,0 +1,19 @@
1
+ test:
2
+ storage: filesystem
3
+ s3:
4
+ bucket: test_archived_attributes
5
+ access_key: your access key
6
+ secret_key: your secret key
7
+ protocol: https
8
+
9
+ development:
10
+ storage: s3
11
+ s3:
12
+ bucket: development_archived_attributes
13
+ access_key: your access key
14
+ secret_key: your secret key
15
+
16
+ anotherenv:
17
+ storage: filesystem
18
+ filesystem:
19
+ archive_root: /tmp/archived_attributes
data/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[lib archived_attributes]))
2
+
3
+ ActiveRecord::Base.send(:include, ArchivedAttributes)
4
+
@@ -0,0 +1,72 @@
1
+ require 'activesupport'
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__),
4
+ %w[ backends filesystem ]))
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[ backends s3 ]))
7
+
8
+ module ArchivedAttributes
9
+
10
+ class ArchivedAttribute
11
+ attr_reader :name, :instance
12
+
13
+ def initialize(name, instance, opts = {})
14
+ @name = name
15
+ @instance = instance
16
+ @dirty = false
17
+
18
+ @_options = ArchivedAttributes::GlobalConfiguration.instance.to_hash.
19
+ merge(opts)
20
+
21
+ @backend = instantiate_backend_from(options)
22
+ end
23
+
24
+ def value
25
+ val = defined?(@stashed_value) ? @stashed_value : @backend.load
26
+ val = compress? ? Zlib::Inflate.inflate(val) : val
27
+ val = marshal? ? Marshal.load(val) : val
28
+ end
29
+
30
+ def value=(other)
31
+ other = marshal? ? Marshal.dump(other) : other
32
+ other = compress? && !other.nil? ? Zlib::Deflate.deflate(other) : other
33
+ @stashed_value = other
34
+ @dirty = true
35
+ end
36
+
37
+ def dirty?
38
+ @dirty
39
+ end
40
+
41
+ # First saves this record to the back-end. If backend storage raises an
42
+ # error, we capture it and add it to the AR validation errors.
43
+ def save
44
+ @backend.save(@stashed_value) if self.dirty?
45
+ end
46
+
47
+ def destroy
48
+ @backend.destroy
49
+ end
50
+
51
+ # Returns a backend object based on the options given (e.g., filesystem,
52
+ # s3).
53
+ def instantiate_backend_from(options)
54
+ "ArchivedAttributes::Backends::#{options[:storage].to_s.camelize}".
55
+ constantize.new(self)
56
+ end
57
+
58
+ def options
59
+ @_options
60
+ end
61
+
62
+ private
63
+
64
+ [:marshal, :compress].each do |sym|
65
+ define_method("#{sym}?") do # def marshal?
66
+ options[sym].nil? ? false : options[sym] # options[:marshal].nil? ? false : options[:marshal]
67
+ end # end
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,58 @@
1
+ module ArchivedAttributes
2
+ module Backends
3
+
4
+ class Filesystem
5
+
6
+ def initialize(archived_attribute)
7
+ @archived_attribute = archived_attribute
8
+ end
9
+
10
+ def save(content)
11
+ create_filesystem_path unless File.exist?(filepath)
12
+ write_to_disk(content)
13
+ end
14
+
15
+ def destroy
16
+ FileUtils.rm_f(filename)
17
+ end
18
+
19
+ def load
20
+ File.read( filename ) if File.exist?( filename )
21
+ end
22
+
23
+ # Returns the full file path + name of this archived attribute
24
+ def filename
25
+ File.join(filepath, @archived_attribute.name.to_s)
26
+ end
27
+
28
+ private
29
+
30
+ # Writes content to disk, or raises an error if the content is unable to
31
+ # be saved
32
+ def write_to_disk(content)
33
+ File.open(filename, 'w') { |f| f.write(content) }
34
+ end
35
+
36
+ def create_filesystem_path
37
+ FileUtils.mkdir_p(filepath)
38
+ end
39
+
40
+ # The file path used for archiving this attribute. Includes either the
41
+ # options[:filesystem][:archive_root] attribute, if available, or the
42
+ # RAILS_ROOT/tmp/archived_attribute_archive/attribute_name.
43
+ def filepath
44
+ config_path = @archived_attribute.options[:filesystem][:archive_root]
45
+
46
+ base_path = config_path || File.join(
47
+ %W[#{RAILS_ROOT} tmp archived_attribute_archive]
48
+ )
49
+
50
+ File.expand_path( File.join(base_path,
51
+ @archived_attribute.name.to_s,
52
+ @archived_attribute.instance.uuid ))
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,58 @@
1
+ require 'right_aws'
2
+
3
+ module ArchivedAttributes
4
+ module Backends
5
+
6
+ class S3
7
+
8
+ def initialize(archived_attribute)
9
+ @archived_attribute = archived_attribute
10
+ @config = ArchivedAttributes::GlobalConfiguration.instance[:s3]
11
+ end
12
+
13
+ def save(content)
14
+ bucket.put( key_name, StringIO.new( content ) ) unless content.nil?
15
+ end
16
+
17
+ def destroy
18
+ bucket.key(key_name).delete
19
+ end
20
+
21
+ def load
22
+ bucket.get(key_name)
23
+ end
24
+
25
+ private
26
+
27
+ def bucket
28
+ @bucket ||= right_aws_s3.bucket(bucket_name)
29
+ end
30
+
31
+ def right_aws_s3
32
+ @s3 ||= RightAws::S3.new(
33
+ @config[:access_key],
34
+ @config[:secret_key]
35
+ )
36
+ end
37
+
38
+ # Returns the bucket name to be used based on attributes of the archived
39
+ # attribute.
40
+ def bucket_name
41
+ @config[:bucket]
42
+ end
43
+
44
+ def key_name
45
+ [ @archived_attribute.instance.class.table_name,
46
+ @archived_attribute.name,
47
+ @archived_attribute.instance.uuid ].join('/')
48
+ end
49
+
50
+ # Returns a string representing whether we use http or https for this
51
+ # connection.
52
+ def protocol
53
+ @config[:protocol] || 'https'
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,49 @@
1
+ module ArchivedAttributes
2
+
3
+ # Singleton class for reading the defaults archived attribute configuration
4
+ # for this environment.
5
+ class GlobalConfiguration
6
+ include Singleton
7
+
8
+ DEFAULTS = HashWithIndifferentAccess.new({
9
+ :storage => 'filesystem',
10
+ :marshal => false,
11
+ :compress => false,
12
+ :s3 => {
13
+ :protocol => 'https'
14
+ },
15
+ :filesystem => {
16
+ :archive_root => nil
17
+ }
18
+ })
19
+
20
+ def [](val)
21
+ config[val]
22
+ end
23
+
24
+ def to_hash
25
+ config
26
+ end
27
+
28
+ def to_s
29
+ config.inspect
30
+ end
31
+
32
+ private
33
+
34
+ def config
35
+ @config ||= HashWithIndifferentAccess.new(
36
+ DEFAULTS.merge(load_yaml_configuration)
37
+ )
38
+
39
+ @config.dup
40
+ end
41
+
42
+ def load_yaml_configuration
43
+ YAML.load_file(
44
+ File.join( RAILS_ROOT, 'config', 'archived_attributes.yml' )
45
+ )[RAILS_ENV]
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,80 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[archived_attributes archived_attribute] ))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[archived_attributes global_configuration] ))
3
+
4
+ require 'uuid'
5
+
6
+ module ArchivedAttributes
7
+
8
+ def self.included(base)
9
+ base.extend(SingletonMethods)
10
+ end
11
+
12
+ module SingletonMethods
13
+
14
+ def archived_attribute(*args)
15
+ attribute = args.first
16
+
17
+ options = args.extract_options!
18
+ options.reverse_merge! :marshalled => false
19
+
20
+ if archived_attribute_definitions.nil?
21
+ write_inheritable_attribute(:archived_attribute_definitions, {})
22
+
23
+ before_save :generate_uuid
24
+ before_save :save_archived_attributes
25
+ before_destroy :destroy_archived_attributes
26
+ end
27
+
28
+ archived_attribute_definitions[attribute] = options
29
+
30
+ self.__send__(:include, InstanceMethods)
31
+
32
+ define_method attribute do
33
+ archive_stash_for(attribute).value
34
+ end
35
+
36
+ define_method "#{attribute}=" do |value|
37
+ archive_stash_for(attribute).value = value
38
+ end
39
+ end
40
+
41
+ # Returns the attachment definitions defined by each call to
42
+ # has_attached_file.
43
+ def archived_attribute_definitions
44
+ read_inheritable_attribute(:archived_attribute_definitions)
45
+ end
46
+
47
+ end
48
+
49
+ module InstanceMethods
50
+ def archive_stash_for(model)
51
+ @_archived_attribute_stashes ||= {}
52
+ @_archived_attribute_stashes[model] ||= ArchivedAttribute.new(
53
+ model, self, self.class.archived_attribute_definitions[model]
54
+ )
55
+ end
56
+
57
+ def each_archived_stash
58
+ self.class.archived_attribute_definitions.each do |name, definition|
59
+ yield(name, archive_stash_for(name))
60
+ end
61
+ end
62
+
63
+ def save_archived_attributes
64
+ each_archived_stash do |name, stash|
65
+ stash.__send__(:save)
66
+ end
67
+ end
68
+
69
+ def destroy_archived_attributes
70
+ each_archived_stash do |name, stash|
71
+ stash.__send__(:destroy)
72
+ end
73
+ end
74
+
75
+ def generate_uuid
76
+ self.uuid = UUID.new.generate if self.new_record?
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,120 @@
1
+ require File.join(File.dirname(__FILE__), %w[ .. spec_helper ])
2
+
3
+ describe ArchivedAttributes::ArchivedAttribute do
4
+ before do
5
+ options = { :storage => 'filesystem' }
6
+ stub_model = stub(:uuid => '43')
7
+ @aa = ArchivedAttributes::ArchivedAttribute.new(:glorp, stub_model, options)
8
+ end
9
+
10
+ describe "#dirty?" do
11
+ it "should return false when a value has not been set" do
12
+ @aa.should_not be_dirty
13
+ end
14
+
15
+ it "should return when the value has been set" do
16
+ @aa.value = 'stuff'
17
+ @aa.should be_dirty
18
+ end
19
+ end
20
+
21
+ describe "#marshal?" do
22
+ it "should return false if configuration option is nil" do
23
+ @aa.expects(:options).returns({:marshal => nil})
24
+ @aa.__send__(:marshal?).should be_false
25
+ end
26
+
27
+ it "should return value from configuration if configuration option is not nil" do
28
+ @aa.expects(:options).returns({:marshal => false}).times(2)
29
+ @aa.__send__(:marshal?).should be_false
30
+ end
31
+ end
32
+
33
+ describe "#compress?" do
34
+ it "should return false if configuration option is nil" do
35
+ @aa.expects(:options).returns({:compress => nil})
36
+ @aa.__send__(:compress?).should be_false
37
+ end
38
+
39
+ it "should return value from configuration if configuration option is not nil" do
40
+ @aa.expects(:options).returns({:compress => false}).times(2)
41
+ @aa.__send__(:compress?).should be_false
42
+ end
43
+ end
44
+
45
+ describe "#destroy" do
46
+ it "should call destroy on the backend object" do
47
+ backend = mock('backend', :destroy => true)
48
+ @aa.instance_variable_set(:'@backend', backend)
49
+ @aa.destroy
50
+ end
51
+ end
52
+
53
+ describe "when marshal is on" do
54
+ before do
55
+ @content = 'mary had a little lamb'
56
+ stub_backend = stub('backend', :load => Marshal.dump(@content))
57
+ @aa.stubs(:options).
58
+ returns({ :storage => 'filesystem', :marshal => true })
59
+ @aa.__send__(:instance_variable_set, :'@backend', stub_backend)
60
+ end
61
+
62
+ it "should call Marshal.load to restore value" do
63
+ Marshal.expects(:load)
64
+ @aa.value
65
+ end
66
+
67
+ it "should call Marshal.dump to save value" do
68
+ Marshal.expects(:dump)
69
+ @aa.value = 'foo'
70
+ end
71
+
72
+ it "should retrieve same content string stored in Marshalled form" do
73
+ @aa.value.should == @content
74
+ end
75
+ end
76
+
77
+ describe "when gzip is on" do
78
+ before do
79
+ @content = "The band formed in 1988 in Oxford"
80
+ stub_backend = stub('backend', :load => Zlib::Deflate.deflate(@content))
81
+ @aa.stubs(:options).
82
+ returns({ :storage => 'filesystem', :compress => true })
83
+ @aa.__send__(:instance_variable_set, :'@backend', stub_backend)
84
+ end
85
+
86
+ it "should call Zlib::Inflate.inflate to restore value" do
87
+ Zlib::Inflate.expects(:inflate)
88
+ @aa.value
89
+ end
90
+
91
+ it "should call Zlib::Deflate.deflate to save value" do
92
+ Zlib::Deflate.expects(:deflate)
93
+ @aa.value = 'foo'
94
+ end
95
+
96
+ it "should retrieve same content string stored in gzip form" do
97
+ @aa.value.should == @content
98
+ end
99
+
100
+ it "should not raise an error with nil content" do
101
+ lambda {
102
+ @aa.value = nil
103
+ }.should_not raise_error
104
+ end
105
+ end
106
+
107
+ describe "when compress and marshal are on" do
108
+ before do
109
+ @content = "The band formed in 1988 in Oxford"
110
+ stub_backend = stub('backend', :load => Zlib::Deflate.deflate(Marshal.dump(@content)))
111
+ @aa.stubs(:options).
112
+ returns({ :storage => 'filesystem', :compress => true, :marshal => true })
113
+ @aa.__send__(:instance_variable_set, :'@backend', stub_backend)
114
+ end
115
+
116
+ it "should retrieve the same content given" do
117
+ @aa.value.should == @content
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,82 @@
1
+ require File.join(File.dirname(__FILE__), %w[ .. .. spec_helper ])
2
+
3
+ require 'tmpdir'
4
+
5
+ describe ArchivedAttributes::Backends::Filesystem do
6
+
7
+ before do
8
+ @unique_path_part = 'archived_attributes_test'
9
+ @path = File.join(Dir.tmpdir, @unique_path_part)
10
+
11
+
12
+ @instance = stub('http_retrieval',
13
+ :uuid => '63d3a120-caca-012b-d468-002332d4f91e',
14
+ :name => :foo
15
+ )
16
+
17
+ aa = ArchivedAttributes::ArchivedAttribute.new(:content, @instance,
18
+ :filesystem => { :archive_root => @path } )
19
+
20
+ @fs = ArchivedAttributes::Backends::Filesystem.new(aa)
21
+ end
22
+
23
+ it "should write to the correct path" do
24
+ @fs.__send__(:filepath).should ==
25
+ File.expand_path(File.join(@path, 'content', @instance.uuid))
26
+ end
27
+
28
+ describe "#save" do
29
+ before do
30
+ if File.exist?(@path)
31
+ err = <<-EOS
32
+ Test directory #{@path} already exists. Please remove it and run the
33
+ test suite again.
34
+ EOS
35
+ raise RuntimeError, err
36
+ else
37
+ @remove_path = true
38
+ FileUtils.mkdir(@path)
39
+ end
40
+ end
41
+
42
+ it "should call methods to create path and save file to disk" do
43
+ @fs.save('test')
44
+ File.exist?(@fs.filename).should be_true
45
+ end
46
+
47
+ after(:all) do
48
+ FileUtils.rm_rf(@path) if @remove_path
49
+ end
50
+
51
+ end
52
+
53
+ describe "#destroy" do
54
+ before do
55
+ if File.exist?(@path)
56
+ err = <<-EOS
57
+ Test directory #{@path} already exists. Please remove it and run the
58
+ test suite again.
59
+ EOS
60
+ raise RuntimeError, err
61
+ else
62
+ @remove_path = true
63
+ FileUtils.mkdir(@path)
64
+ end
65
+ end
66
+
67
+ it "should call methods to remove path and file" do
68
+ @fs.save('test')
69
+ File.exist?(@fs.filename).should be_true
70
+
71
+ @fs.destroy
72
+ File.exist?(@fs.filename).should be_false
73
+ end
74
+
75
+ after(:all) do
76
+ FileUtils.rm_rf(@path) if @remove_path
77
+ end
78
+
79
+ end
80
+
81
+
82
+ end
@@ -0,0 +1,79 @@
1
+ require File.join(File.dirname(__FILE__), %w[ .. .. spec_helper ])
2
+
3
+ describe ArchivedAttributes::Backends::S3 do
4
+
5
+ before do
6
+ @instance = stub('ar_instance',
7
+ :uuid => '63d3a120-caca-012b-d468-002332d4f91e',
8
+ :table_name => 'glorps'
9
+ )
10
+
11
+ @aa = ArchivedAttributes::ArchivedAttribute.new(:stuff, @instance)
12
+ @s3 = ArchivedAttributes::Backends::S3.new(@aa)
13
+ @config = ArchivedAttributes::GlobalConfiguration.instance
14
+ end
15
+
16
+ describe "#initialize" do
17
+ it "should initialize an s3 object without error" do
18
+ lambda { ArchivedAttributes::Backends::S3.new(@aa) }.should_not raise_error
19
+ end
20
+ end
21
+
22
+ describe "#protocol" do
23
+ it "should be https by default" do
24
+ @s3.__send__(:protocol).should == "https"
25
+ end
26
+
27
+ it "should use http if specified in the configuration object" do
28
+ config = { :protocol => 'http' }
29
+ @s3.instance_variable_set(:"@config", config)
30
+
31
+ @s3.__send__(:protocol).should == "http"
32
+ end
33
+
34
+ end
35
+
36
+ describe "#load" do
37
+ it "should call method to load data from s3" do
38
+ bucket = mock('bucket')
39
+ bucket.expects(:get).once
40
+ aws_s3 = mock('aws_s3')
41
+ aws_s3.expects(:bucket).returns(bucket)
42
+ @s3.expects(:key_name).returns('some-key')
43
+ @s3.expects(:right_aws_s3).returns(aws_s3)
44
+ @s3.load
45
+ end
46
+ end
47
+
48
+ describe "#save" do
49
+ it "should call method to store data in s3" do
50
+ bucket = mock('bucket')
51
+ content = 'hey'
52
+ key = 'fookey'
53
+ @s3.expects(:key_name).returns(key)
54
+ bucket.expects(:put).once
55
+ aws_s3 = mock('aws_s3')
56
+ aws_s3.expects(:bucket).returns(bucket)
57
+ @s3.expects(:right_aws_s3).returns(aws_s3)
58
+ @s3.save(content)
59
+ end
60
+ end
61
+
62
+ describe "#destroy" do
63
+ it "should call method to delete key" do
64
+ key = mock('key', :delete => true)
65
+ bucket = mock('bucket', :key => key)
66
+ aws_s3 = mock('aws_s3')
67
+ aws_s3.expects(:bucket).returns(bucket)
68
+ @s3.expects(:right_aws_s3).returns(aws_s3)
69
+ @s3.expects(:key_name).returns('foo-key')
70
+ @s3.destroy
71
+ end
72
+ end
73
+
74
+ describe "#bucket_name" do
75
+ it "should be based on the attribute class and model" do
76
+ @s3.__send__(:bucket_name).should == @config[:s3]['bucket']
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,72 @@
1
+ require File.join(File.dirname(__FILE__), %w[ .. spec_helper ])
2
+
3
+ describe ArchivedAttributes::GlobalConfiguration do
4
+ before do
5
+ @conf = ArchivedAttributes::GlobalConfiguration.instance
6
+ end
7
+
8
+ describe "defaults" do
9
+ it "should set default marshal value to false" do
10
+ ArchivedAttributes::GlobalConfiguration::DEFAULTS[:marshal].should == false
11
+ end
12
+
13
+ it "should set gzip value to false" do
14
+ ArchivedAttributes::GlobalConfiguration::DEFAULTS[:marshal].should == false
15
+ end
16
+ end
17
+
18
+ it "should read default access key from the configuration file" do
19
+ @conf[:s3]['access_key'].should == 'your access key'
20
+ end
21
+
22
+ it "should the default secret key from configuration" do
23
+ @conf[:s3]['secret_key'].should == 'your secret key'
24
+ end
25
+
26
+ it "should read the default bucket from the configuration file" do
27
+ @conf[:s3]['bucket'].should == 'test_archived_attributes'
28
+ end
29
+
30
+ describe "#to_s" do
31
+ it "should return a string" do
32
+ @conf.to_s.should be_an_instance_of(String)
33
+ end
34
+ end
35
+
36
+ describe "hash cloning" do
37
+ it "should be able to alter a Hash without affecting the original object" do
38
+ conf = @conf.to_hash
39
+ previous = @conf[:storage]
40
+ conf[:storage] = 'foo'
41
+ @conf[:storage].should == previous
42
+ end
43
+
44
+ it "should not affect deeply nested attributes when values are changed" do
45
+ conf = @conf.to_hash
46
+ previous = @conf[:s3][:protocol]
47
+ conf[:s3][:protocol] = 'puddle'
48
+ @conf[:s3][:protocol].should == previous
49
+ end
50
+ end
51
+
52
+ describe "#to_hash" do
53
+ it "should return an instance of Hash" do
54
+ @conf.to_hash.should be_an_instance_of(HashWithIndifferentAccess)
55
+ end
56
+ end
57
+
58
+ describe "when an option is not specified in the yaml config file" do
59
+ it "should have a section for s3 options in hash" do
60
+ @conf[:s3].should_not be_nil
61
+ end
62
+
63
+ it "should default to https for protocol" do
64
+ @conf[:s3][:protocol].should == 'https'
65
+ end
66
+
67
+ it "should set default storage attribute to :filesystem" do
68
+ @conf[:storage].should == 'filesystem'
69
+ end
70
+ end
71
+
72
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsl-archived_attributes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Justin Leitgeb
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-25 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: right_aws
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">"
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.0
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: assaf-uuid
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">"
30
+ - !ruby/object:Gem::Version
31
+ version: 0.0.0
32
+ version:
33
+ description: ArchivedAttributes allows for data to be saved to a backend other than the rdbms
34
+ email: justin@phq.org
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files: []
40
+
41
+ files:
42
+ - Rakefile
43
+ - archived_attributes.gemspec
44
+ - init.rb
45
+ - config/archived_attributes.yml
46
+ - lib/archived_attributes.rb
47
+ - lib/archived_attributes/archived_attribute.rb
48
+ - lib/archived_attributes/global_configuration.rb
49
+ - lib/archived_attributes/backends/s3.rb
50
+ - lib/archived_attributes/backends/filesystem.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/jsl/archived_attributes
53
+ post_install_message:
54
+ rdoc_options: []
55
+
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.2.0
74
+ signing_key:
75
+ specification_version: 2
76
+ summary: Rails plugin to save content to a pluggable back-end
77
+ test_files:
78
+ - spec/archived_attributes/global_configuration_spec.rb
79
+ - spec/archived_attributes/archived_attribute_spec.rb
80
+ - spec/archived_attributes/backends/filesystem_spec.rb
81
+ - spec/archived_attributes/backends/s3_spec.rb