file_marshal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2e27933be6ab40fee02ab09b35b2b83db25c593c
4
+ data.tar.gz: 2f8c3403ab7b31073a571ed14b1697abfab22595
5
+ SHA512:
6
+ metadata.gz: b810e76f72917eb4ef28a9494e8ff274a6d1dd0342dc66aebd8d8e6db2ddcc7b9735cb992bd9d9db7acc758237bf77a98b678f6c4f6d7309bca749e91fe25ebc
7
+ data.tar.gz: 9c03f99ee34250ce8eecdd300867a24738ebf702f3fbc952622585153aff19c516ba29a4ead12198536e5e6676474d9155308be8c3fe830f31093e9cdfa47e4c
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ **/*.DS_Store
20
+ spec/support/new_commodore.jpg
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1,6 @@
1
+ rvm_install_on_use_flag=1
2
+ rvm_trust_rvmrcs_flag=1
3
+ rvm_gemset_create_on_use_flag=1
4
+
5
+ rvm use 2.0.0@file_marshal --create
6
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in file_marshal.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 socialchorus
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,51 @@
1
+ # FileMarshal
2
+
3
+ FileMarshal has the goal of providing easy ways to serialize files to send across the wire. Marshal is unable to dump files because they are IO and potentially limitless. In practice, files are finite and we want to move them around. Enjoy!
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'file_marshal'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install file_marshal
18
+
19
+ ## Usage
20
+
21
+ FileMarshal uses the class methods `FileMarshal.dump(file)` and `FileMarshal.load(string)` to pack and unpack files. As with other types of serialization including YAML, JSON, and Marshal, the files are packaged as a string.
22
+
23
+ In order to serialize a file into a string you could use this code:
24
+
25
+ file = File.new(my_path, 'r')
26
+ serialized_file = FileMarshal.dump(file) # => a string of data that can be read again
27
+
28
+ When you are ready to read these serializations back into a file, use the load method:
29
+
30
+ tempfile = FileMarshal.load(serialized_file)
31
+
32
+ If you are looking for a file with a specific path, rather than a tempfile, pass the path in as a second argument:
33
+
34
+ file = FileMarshal.load(serialized_file, new_path)
35
+
36
+ In reality, this string is JSON, and under the covers there are classes that work with hashes to pass the data around. In many instances you will want to use these underlying classes instead of the `.dump` and `.load` methods:
37
+
38
+ hash = FileMarshal::Dumper.new(file).to_hash
39
+
40
+ tempfile = FileMarshal::Loader.new(hash).tempfile
41
+ file = FileMarshal::Loader.new(hash).to_file(my_great_path)
42
+
43
+ Everything is very small objects, which should make other usages as easy as inspecting the code.
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'file_marshal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "file_marshal"
8
+ spec.version = FileMarshal::VERSION
9
+ spec.authors = ["socialchorus", "Matt Mills", "Kane Baccigalupi"]
10
+ spec.email = ["developers@socialchorus.com"]
11
+ spec.description = %q{Serializes files to hashes of strings for serialization over various protocols}
12
+ spec.summary = %q{Serializes files to hashes of strings for serialization over various protocols}
13
+ spec.homepage = "http://github.com/socialchorus/file_marshal"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'superbolt'
27
+ end
@@ -0,0 +1,15 @@
1
+ require 'tempfile'
2
+ require 'json'
3
+ require 'time'
4
+
5
+ require 'active_support/core_ext/module/delegation'
6
+ require 'active_support/core_ext/hash'
7
+
8
+ require "file_marshal/version"
9
+ require "file_marshal/dumper"
10
+ require "file_marshal/loader"
11
+ require "file_marshal/file_attributes"
12
+ require "file_marshal/writer"
13
+ require "file_marshal/writer/temp"
14
+ require "file_marshal/writer/file"
15
+ require "file_marshal/facade"
@@ -0,0 +1,22 @@
1
+ module FileMarshal
2
+ class Dumper
3
+ attr_reader :file
4
+
5
+ def initialize(file)
6
+ @file = file
7
+ end
8
+
9
+ def to_hash
10
+ {
11
+ updated_at: file.mtime,
12
+ name: File.basename(file.path),
13
+ content: content
14
+ }
15
+ end
16
+
17
+ def content
18
+ file.rewind
19
+ file.read
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,12 @@
1
+ module FileMarshal
2
+ def self.dump(file)
3
+ hash = FileMarshal::Dumper.new(file).to_hash
4
+ hash.to_json
5
+ end
6
+
7
+ def self.load(string, path=nil)
8
+ hash = JSON.parse(string)
9
+ loader = FileMarshal::Loader.new(hash)
10
+ path ? loader.to_file(path) : loader.tempfile
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ module FileMarshal
2
+ class FileAttributes < Struct.new(:name, :content, :updated_at)
3
+ end
4
+ end
@@ -0,0 +1,23 @@
1
+ module FileMarshal
2
+ class Loader
3
+ attr_reader :attributes, :file
4
+
5
+ def initialize(opts)
6
+ opts.symbolize_keys!
7
+ @attributes = FileAttributes.new(
8
+ opts[:name], opts[:content], opts[:updated_at]
9
+ )
10
+ end
11
+
12
+ delegate :name,
13
+ to: :attributes
14
+
15
+ def tempfile
16
+ Writer::Temp.new(attributes).build
17
+ end
18
+
19
+ def to_file(path)
20
+ Writer::File.new(attributes, path).build
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module FileMarshal
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,36 @@
1
+ module FileMarshal
2
+ class Writer
3
+ attr_reader :attributes, :file
4
+
5
+ def initialize(attributes)
6
+ @attributes = attributes
7
+ end
8
+
9
+ delegate :name, :content, :updated_at,
10
+ to: :attributes
11
+
12
+ def build
13
+ write
14
+ set_time
15
+ prepare
16
+ end
17
+
18
+ def file
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def write
23
+ file.write(content)
24
+ file
25
+ end
26
+
27
+ def set_time
28
+ ::File.utime(file.atime, Time.parse(updated_at), file.path)
29
+ end
30
+
31
+ def prepare
32
+ file.rewind
33
+ file
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ module FileMarshal
2
+ class Writer
3
+ class File < Writer
4
+ attr_reader :path
5
+
6
+ def initialize(attributes, path)
7
+ @attributes = attributes
8
+ @path = path
9
+ end
10
+
11
+ def file
12
+ @file ||= ::File.new(path, "w+")
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ module FileMarshal
2
+ class Writer
3
+ class Temp < Writer
4
+ def file
5
+ @file ||= Tempfile.new(name)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ describe FileMarshal::Dumper do
4
+ let(:file) { File.open(File.dirname(__FILE__) + '/support/commodore.jpg') }
5
+ let(:dumper) { FileMarshal::Dumper.new(file) }
6
+
7
+ describe "#to_hash" do
8
+ let(:attributes) { dumper.to_hash }
9
+
10
+ it "gets the file name" do
11
+ attributes[:name].should == "commodore.jpg"
12
+ end
13
+
14
+ it "gets the updated at time for the file" do
15
+ attributes[:updated_at].should == file.mtime
16
+ end
17
+
18
+ it "takes a file and turns it into a string" do
19
+ content = file.read
20
+ attributes[:content].should == content
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileMarshal do
4
+ let(:path) { File.dirname(__FILE__) + '/support/commodore.jpg' }
5
+ let(:hash) { {hello: 'world'} }
6
+
7
+ describe '.dump' do
8
+ let(:dumper) { double('dumper', to_hash: hash) }
9
+
10
+ let(:file) { File.open(path) }
11
+
12
+ it "converts to a string using the Dumper" do
13
+ FileMarshal::Dumper.should_receive(:new).with(file).and_return(dumper)
14
+
15
+ FileMarshal.dump(file).should == hash.to_json
16
+ end
17
+ end
18
+
19
+ describe '.load' do
20
+ let(:loader) { double("writer", to_file: "file", tempfile: 'tempfile') }
21
+
22
+ context 'when a path is provided' do
23
+ it "returns a file with the path" do
24
+ FileMarshal::Loader.should_receive(:new)
25
+ .with({'hello' => 'world'})
26
+ .and_return(loader)
27
+ loader.should_receive(:to_file).with(path).and_return('my file')
28
+
29
+ FileMarshal.load(hash.to_json, path).should == 'my file'
30
+ end
31
+ end
32
+
33
+ context 'when a path is not provided' do
34
+ it "returns a tempfile" do
35
+ FileMarshal::Loader.should_receive(:new)
36
+ .with({'hello' => 'world'})
37
+ .and_return(loader)
38
+ loader.should_receive(:tempfile).and_return('tempfile')
39
+
40
+ FileMarshal.load(hash.to_json).should == 'tempfile'
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileMarshal::Loader do
4
+ let(:file) { File.open(File.dirname(__FILE__) + '/support/commodore.jpg') }
5
+ let(:attributes) { JSON.parse(FileMarshal::Dumper.new(file).to_hash.to_json) }
6
+ let(:loader) { FileMarshal::Loader.new(attributes) }
7
+
8
+ describe '#tempfile' do
9
+ let(:new_file) { loader.tempfile }
10
+
11
+ it "is a tempfile" do
12
+ new_file.should be_a Tempfile
13
+ end
14
+
15
+ it "should have the right mtime" do
16
+ new_file.mtime.should == attributes[:updated_at]
17
+ end
18
+
19
+ it "should have the right content" do
20
+ new_file.read.should == attributes[:content]
21
+ end
22
+ end
23
+
24
+ describe '#file' do
25
+ let(:new_file) { loader.to_file(new_commodore_path) }
26
+ let(:new_commodore_path) { File.dirname(__FILE__) + '/support/new_commodore.jpg' }
27
+
28
+ before do
29
+ File.delete(new_commodore_path) if File.exist?(new_commodore_path)
30
+ end
31
+
32
+ it "creates the file" do
33
+ loader.to_file(new_commodore_path)
34
+ File.exist?(new_commodore_path).should be_true
35
+ end
36
+
37
+ it "should have the right mtime" do
38
+ new_file.mtime.should == attributes[:updated_at]
39
+ end
40
+
41
+ it "should have the right content" do
42
+ new_file.read.should == attributes[:content]
43
+ end
44
+ end
45
+
46
+ describe '#name' do
47
+ it "gets it from the attributes passed in" do
48
+ loader.name.should == 'commodore.jpg'
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ here = File.dirname(__FILE__)
8
+ require "#{here}/../lib/file_marshal"
9
+ Dir["#{here}/support/**/*.rb"].each {|f| require f}
10
+
11
+ RSpec.configure do |config|
12
+ config.treat_symbols_as_metadata_keys_with_true_values = true
13
+ config.run_all_when_everything_filtered = true
14
+ config.filter_run :focus
15
+
16
+ # Run specs in random order to surface order dependencies. If you find an
17
+ # order dependency and want to debug it, you can fix the order by providing
18
+ # the seed, which is printed after each run.
19
+ # --seed 1234
20
+ config.order = 'random'
21
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: file_marshal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - socialchorus
8
+ - Matt Mills
9
+ - Kane Baccigalupi
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-02-07 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: bundler
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: '1.3'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ version: '1.3'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rake
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: rspec
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: superbolt
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ description: Serializes files to hashes of strings for serialization over various
86
+ protocols
87
+ email:
88
+ - developers@socialchorus.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - .gitignore
94
+ - .rspec
95
+ - .rvmrc
96
+ - Gemfile
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - file_marshal.gemspec
101
+ - lib/file_marshal.rb
102
+ - lib/file_marshal/dumper.rb
103
+ - lib/file_marshal/facade.rb
104
+ - lib/file_marshal/file_attributes.rb
105
+ - lib/file_marshal/loader.rb
106
+ - lib/file_marshal/version.rb
107
+ - lib/file_marshal/writer.rb
108
+ - lib/file_marshal/writer/file.rb
109
+ - lib/file_marshal/writer/temp.rb
110
+ - spec/dumper_spec.rb
111
+ - spec/file_marshal_spec.rb
112
+ - spec/loader_spec.rb
113
+ - spec/spec_helper.rb
114
+ - spec/support/commodore.jpg
115
+ homepage: http://github.com/socialchorus/file_marshal
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.0.3
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: Serializes files to hashes of strings for serialization over various protocols
139
+ test_files:
140
+ - spec/dumper_spec.rb
141
+ - spec/file_marshal_spec.rb
142
+ - spec/loader_spec.rb
143
+ - spec/spec_helper.rb
144
+ - spec/support/commodore.jpg