joint 0.5 → 0.5.5
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/.gitignore +7 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +49 -0
- data/Rakefile +12 -0
- data/joint.gemspec +25 -0
- data/lib/joint/attachment_proxy.rb +35 -0
- data/lib/joint/class_methods.rb +49 -0
- data/lib/joint/instance_methods.rb +54 -0
- data/lib/joint/io.rb +14 -0
- data/lib/joint/version.rb +1 -1
- data/lib/joint.rb +21 -131
- data/specs.watchr +38 -0
- data/test/fixtures/example.m4r +0 -0
- data/test/fixtures/font.eot +0 -0
- data/test/helper.rb +40 -0
- data/test/joint/test_io.rb +28 -0
- data/test/test_joint.rb +86 -40
- metadata +25 -9
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
joint (0.5.2)
|
|
5
|
+
mime-types
|
|
6
|
+
mongo_mapper (~> 0.8.6)
|
|
7
|
+
wand (~> 0.4)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: http://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
activesupport (3.0.3)
|
|
13
|
+
bson (1.1.5)
|
|
14
|
+
bson_ext (1.1.5)
|
|
15
|
+
i18n (0.4.2)
|
|
16
|
+
jnunemaker-matchy (0.4.0)
|
|
17
|
+
jnunemaker-validatable (1.8.4)
|
|
18
|
+
activesupport (>= 2.3.4)
|
|
19
|
+
mime-types (1.16)
|
|
20
|
+
mocha (0.9.10)
|
|
21
|
+
rake
|
|
22
|
+
mongo (1.1.5)
|
|
23
|
+
bson (>= 1.1.5)
|
|
24
|
+
mongo_mapper (0.8.6)
|
|
25
|
+
activesupport (>= 2.3.4)
|
|
26
|
+
jnunemaker-validatable (~> 1.8.4)
|
|
27
|
+
plucky (~> 0.3.6)
|
|
28
|
+
plucky (0.3.6)
|
|
29
|
+
mongo (~> 1.1)
|
|
30
|
+
rake (0.8.7)
|
|
31
|
+
safe_shell (1.0.0)
|
|
32
|
+
shoulda (2.11.3)
|
|
33
|
+
wand (0.4)
|
|
34
|
+
mime-types
|
|
35
|
+
safe_shell (~> 1.0.0)
|
|
36
|
+
|
|
37
|
+
PLATFORMS
|
|
38
|
+
ruby
|
|
39
|
+
|
|
40
|
+
DEPENDENCIES
|
|
41
|
+
bson_ext (~> 1.1)
|
|
42
|
+
i18n (= 0.4.2)
|
|
43
|
+
jnunemaker-matchy
|
|
44
|
+
joint!
|
|
45
|
+
mime-types
|
|
46
|
+
mocha
|
|
47
|
+
mongo_mapper (~> 0.8.6)
|
|
48
|
+
shoulda
|
|
49
|
+
wand (~> 0.4)
|
data/Rakefile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'bundler'
|
|
2
|
+
Bundler::GemHelper.install_tasks
|
|
3
|
+
|
|
4
|
+
require 'rake/testtask'
|
|
5
|
+
Rake::TestTask.new do |test|
|
|
6
|
+
test.libs << 'lib' << 'test'
|
|
7
|
+
test.pattern = 'test/**/test_*.rb'
|
|
8
|
+
test.ruby_opts = ['-rubygems']
|
|
9
|
+
test.verbose = true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
task :default => :test
|
data/joint.gemspec
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require File.expand_path('../lib/joint/version', __FILE__)
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |s|
|
|
5
|
+
s.name = "joint"
|
|
6
|
+
s.summary = %Q{MongoMapper and GridFS joined in file upload love.}
|
|
7
|
+
s.description = %Q{MongoMapper and GridFS joined in file upload love.}
|
|
8
|
+
s.email = "nunemaker@gmail.com"
|
|
9
|
+
s.homepage = "http://github.com/jnunemaker/joint"
|
|
10
|
+
s.authors = ["John Nunemaker"]
|
|
11
|
+
s.version = Joint::Version
|
|
12
|
+
|
|
13
|
+
s.add_dependency 'wand', '~> 0.4'
|
|
14
|
+
s.add_dependency 'mime-types'
|
|
15
|
+
s.add_dependency 'mongo_mapper', '~> 0.8.6'
|
|
16
|
+
|
|
17
|
+
s.add_development_dependency 'shoulda'
|
|
18
|
+
s.add_development_dependency 'mocha'
|
|
19
|
+
s.add_development_dependency 'jnunemaker-matchy'
|
|
20
|
+
|
|
21
|
+
s.files = `git ls-files`.split("\n")
|
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
24
|
+
s.require_paths = ["lib"]
|
|
25
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Joint
|
|
2
|
+
class AttachmentProxy
|
|
3
|
+
def initialize(instance, name)
|
|
4
|
+
@instance, @name = instance, name
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def id
|
|
8
|
+
@instance.send("#{@name}_id")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def name
|
|
12
|
+
@instance.send("#{@name}_name")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def size
|
|
16
|
+
@instance.send("#{@name}_size")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def type
|
|
20
|
+
@instance.send("#{@name}_type")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def nil?
|
|
24
|
+
!@instance.send("#{@name}?")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def grid_io
|
|
28
|
+
@grid_io ||= @instance.grid.get(id)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def method_missing(method, *args, &block)
|
|
32
|
+
grid_io.send(method, *args, &block)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Joint
|
|
2
|
+
module ClassMethods
|
|
3
|
+
def attachment_accessor_module
|
|
4
|
+
@attachment_accessor_module ||= Module.new
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def attachment(name, options = {})
|
|
8
|
+
options.symbolize_keys!
|
|
9
|
+
name = name.to_sym
|
|
10
|
+
|
|
11
|
+
self.attachment_names << name
|
|
12
|
+
|
|
13
|
+
after_save :save_attachments
|
|
14
|
+
after_save :destroy_nil_attachments
|
|
15
|
+
before_destroy :destroy_all_attachments
|
|
16
|
+
|
|
17
|
+
key :"#{name}_id", ObjectId
|
|
18
|
+
key :"#{name}_name", String
|
|
19
|
+
key :"#{name}_size", Integer
|
|
20
|
+
key :"#{name}_type", String
|
|
21
|
+
|
|
22
|
+
validates_presence_of(name) if options[:required]
|
|
23
|
+
|
|
24
|
+
attachment_accessor_module.module_eval <<-EOC
|
|
25
|
+
def #{name}
|
|
26
|
+
@#{name} ||= AttachmentProxy.new(self, :#{name})
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def #{name}?
|
|
30
|
+
!nil_attachments.include?(:#{name}) && send(:#{name}_id?)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def #{name}=(file)
|
|
34
|
+
if file.nil?
|
|
35
|
+
nil_attachments << :#{name}
|
|
36
|
+
assigned_attachments.delete(:#{name})
|
|
37
|
+
else
|
|
38
|
+
send("#{name}_id=", BSON::ObjectId.new) if send("#{name}_id").nil?
|
|
39
|
+
send("#{name}_name=", Joint.name(file))
|
|
40
|
+
send("#{name}_size=", Joint.size(file))
|
|
41
|
+
send("#{name}_type=", Joint.type(file))
|
|
42
|
+
assigned_attachments[:#{name}] = file
|
|
43
|
+
nil_attachments.delete(:#{name})
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
EOC
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Joint
|
|
2
|
+
module InstanceMethods
|
|
3
|
+
def grid
|
|
4
|
+
@grid ||= Mongo::Grid.new(database)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
def assigned_attachments
|
|
9
|
+
@assigned_attachments ||= {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def nil_attachments
|
|
13
|
+
@nil_attachments ||= Set.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# IO must respond to read and rewind
|
|
17
|
+
def save_attachments
|
|
18
|
+
assigned_attachments.each_pair do |name, io|
|
|
19
|
+
next unless io.respond_to?(:read)
|
|
20
|
+
io.rewind if io.respond_to?(:rewind)
|
|
21
|
+
grid.delete(send(name).id)
|
|
22
|
+
grid.put(io.read, {
|
|
23
|
+
:_id => send(name).id,
|
|
24
|
+
:filename => send(name).name,
|
|
25
|
+
:content_type => send(name).type,
|
|
26
|
+
})
|
|
27
|
+
end
|
|
28
|
+
assigned_attachments.clear
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def destroy_nil_attachments
|
|
32
|
+
# currently MM does not send sets to instance as well
|
|
33
|
+
nil_attachments.each do |name|
|
|
34
|
+
grid.delete(send(name).id)
|
|
35
|
+
send(:"#{name}_id=", nil)
|
|
36
|
+
send(:"#{name}_size=", nil)
|
|
37
|
+
send(:"#{name}_type=", nil)
|
|
38
|
+
send(:"#{name}_name=", nil)
|
|
39
|
+
set({
|
|
40
|
+
:"#{name}_id" => nil,
|
|
41
|
+
:"#{name}_size" => nil,
|
|
42
|
+
:"#{name}_type" => nil,
|
|
43
|
+
:"#{name}_name" => nil,
|
|
44
|
+
})
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
nil_attachments.clear
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def destroy_all_attachments
|
|
51
|
+
self.class.attachment_names.map { |name| grid.delete(send(name).id) }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/joint/io.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Joint
|
|
2
|
+
class IO
|
|
3
|
+
attr_accessor :name, :content, :type, :size
|
|
4
|
+
|
|
5
|
+
def initialize(attrs={})
|
|
6
|
+
attrs.each { |key, value| send("#{key}=", value) }
|
|
7
|
+
@type ||= 'plain/text'
|
|
8
|
+
@size ||= @content.size unless @content.nil?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
alias path name
|
|
12
|
+
alias read content
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/joint/version.rb
CHANGED
data/lib/joint.rb
CHANGED
|
@@ -3,150 +3,40 @@ require 'mime/types'
|
|
|
3
3
|
require 'wand'
|
|
4
4
|
|
|
5
5
|
module Joint
|
|
6
|
-
autoload :Version, 'joint/version'
|
|
7
|
-
|
|
8
6
|
def self.configure(model)
|
|
9
7
|
model.class_inheritable_accessor :attachment_names
|
|
10
8
|
model.attachment_names = Set.new
|
|
11
9
|
model.send(:include, model.attachment_accessor_module)
|
|
12
10
|
end
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def attachment(name, options = {})
|
|
20
|
-
options.symbolize_keys!
|
|
21
|
-
name = name.to_sym
|
|
22
|
-
|
|
23
|
-
self.attachment_names << name
|
|
24
|
-
|
|
25
|
-
after_save :save_attachments
|
|
26
|
-
after_save :destroy_nil_attachments
|
|
27
|
-
before_destroy :destroy_all_attachments
|
|
28
|
-
|
|
29
|
-
key :"#{name}_id", ObjectId
|
|
30
|
-
key :"#{name}_name", String
|
|
31
|
-
key :"#{name}_size", Integer
|
|
32
|
-
key :"#{name}_type", String
|
|
33
|
-
|
|
34
|
-
validates_presence_of(name) if options[:required]
|
|
35
|
-
|
|
36
|
-
attachment_accessor_module.module_eval <<-EOC
|
|
37
|
-
def #{name}
|
|
38
|
-
@#{name} ||= AttachmentProxy.new(self, :#{name})
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def #{name}?
|
|
42
|
-
!nil_attachments.include?(:#{name}) && send(:#{name}_id?)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def #{name}=(file)
|
|
46
|
-
if file.nil?
|
|
47
|
-
nil_attachments << :#{name}
|
|
48
|
-
assigned_attachments.delete(:#{name})
|
|
49
|
-
else
|
|
50
|
-
send("#{name}_id=", BSON::ObjectId.new) if send("#{name}_id").nil?
|
|
51
|
-
send("#{name}_size=", File.size(file))
|
|
52
|
-
send("#{name}_type=", Wand.wave(file.path))
|
|
53
|
-
send("#{name}_name=", Joint.file_name(file))
|
|
54
|
-
assigned_attachments[:#{name}] = file
|
|
55
|
-
nil_attachments.delete(:#{name})
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
EOC
|
|
12
|
+
def self.name(file)
|
|
13
|
+
if file.respond_to?(:original_filename)
|
|
14
|
+
file.original_filename
|
|
15
|
+
else
|
|
16
|
+
File.basename(file.path)
|
|
59
17
|
end
|
|
60
18
|
end
|
|
61
19
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
20
|
+
def self.size(file)
|
|
21
|
+
if file.respond_to?(:size)
|
|
22
|
+
file.size
|
|
23
|
+
else
|
|
24
|
+
File.size(file)
|
|
65
25
|
end
|
|
66
|
-
|
|
67
|
-
private
|
|
68
|
-
def assigned_attachments
|
|
69
|
-
@assigned_attachments ||= {}
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def nil_attachments
|
|
73
|
-
@nil_attachments ||= Set.new
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# IO must respond to read and rewind
|
|
77
|
-
def save_attachments
|
|
78
|
-
assigned_attachments.each_pair do |name, io|
|
|
79
|
-
next unless io.respond_to?(:read)
|
|
80
|
-
io.rewind if io.respond_to?(:rewind)
|
|
81
|
-
grid.delete(send(name).id)
|
|
82
|
-
grid.put(io.read, {
|
|
83
|
-
:_id => send(name).id,
|
|
84
|
-
:filename => send(name).name,
|
|
85
|
-
:content_type => send(name).type,
|
|
86
|
-
})
|
|
87
|
-
end
|
|
88
|
-
assigned_attachments.clear
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def destroy_nil_attachments
|
|
92
|
-
# currently MM does not send sets to instance as well
|
|
93
|
-
nil_attachments.each do |name|
|
|
94
|
-
grid.delete(send(name).id)
|
|
95
|
-
send(:"#{name}_id=", nil)
|
|
96
|
-
send(:"#{name}_size=", nil)
|
|
97
|
-
send(:"#{name}_type=", nil)
|
|
98
|
-
send(:"#{name}_name=", nil)
|
|
99
|
-
set({
|
|
100
|
-
:"#{name}_id" => nil,
|
|
101
|
-
:"#{name}_size" => nil,
|
|
102
|
-
:"#{name}_type" => nil,
|
|
103
|
-
:"#{name}_name" => nil,
|
|
104
|
-
})
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
nil_attachments.clear
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def destroy_all_attachments
|
|
111
|
-
self.class.attachment_names.map { |name| grid.delete(send(name).id) }
|
|
112
|
-
end
|
|
113
26
|
end
|
|
114
27
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def id
|
|
121
|
-
@instance.send("#{@name}_id")
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def name
|
|
125
|
-
@instance.send("#{@name}_name")
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def size
|
|
129
|
-
@instance.send("#{@name}_size")
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def type
|
|
133
|
-
@instance.send("#{@name}_type")
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def nil?
|
|
137
|
-
!@instance.send("#{@name}?")
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def grid_io
|
|
141
|
-
@grid_io ||= @instance.grid.get(id)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def method_missing(method, *args, &block)
|
|
145
|
-
grid_io.send(method, *args, &block)
|
|
146
|
-
end
|
|
28
|
+
def self.type(file)
|
|
29
|
+
return file.type if file.is_a?(Joint::IO)
|
|
30
|
+
Wand.wave(file.path, :original_filename => Joint.name(file))
|
|
147
31
|
end
|
|
148
32
|
|
|
149
|
-
|
|
150
|
-
|
|
33
|
+
private
|
|
34
|
+
def self.blank?(str)
|
|
35
|
+
str.nil? || str !~ /\S/
|
|
151
36
|
end
|
|
152
37
|
end
|
|
38
|
+
|
|
39
|
+
require 'joint/class_methods'
|
|
40
|
+
require 'joint/instance_methods'
|
|
41
|
+
require 'joint/attachment_proxy'
|
|
42
|
+
require 'joint/io'
|
data/specs.watchr
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
def run(cmd)
|
|
2
|
+
puts(cmd)
|
|
3
|
+
output = ""
|
|
4
|
+
IO.popen(cmd) do |com|
|
|
5
|
+
com.each_char do |c|
|
|
6
|
+
print c
|
|
7
|
+
output << c
|
|
8
|
+
$stdout.flush
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
output
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run_test_file(file)
|
|
15
|
+
run %Q(ruby -I"lib:test" -rubygems #{file})
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run_all_tests
|
|
19
|
+
run "rake test"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def related_test_files(path)
|
|
23
|
+
Dir['test/**/*.rb'].select { |file| file =~ /test_#{File.basename(path)}/ }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
watch('test/test_helper\.rb') { system('clear'); run_all_tests }
|
|
27
|
+
watch('test/.*test_.*\.rb') { |m| system('clear'); run_test_file(m[0]) }
|
|
28
|
+
watch('lib/.*') { |m| related_test_files(m[0]).each { |file| run_test_file(file) } }
|
|
29
|
+
|
|
30
|
+
# Ctrl-\
|
|
31
|
+
Signal.trap('QUIT') do
|
|
32
|
+
puts " --- Running all tests ---\n\n"
|
|
33
|
+
run_all_tests
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Ctrl-C
|
|
37
|
+
Signal.trap('INT') { abort("\n") }
|
|
38
|
+
|
|
Binary file
|
|
Binary file
|
data/test/helper.rb
CHANGED
|
@@ -37,4 +37,44 @@ class Test::Unit::TestCase
|
|
|
37
37
|
def assert_no_grid_difference(&block)
|
|
38
38
|
assert_grid_difference(0, &block)
|
|
39
39
|
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Asset
|
|
43
|
+
include MongoMapper::Document
|
|
44
|
+
plugin Joint
|
|
45
|
+
|
|
46
|
+
key :title, String
|
|
47
|
+
attachment :image
|
|
48
|
+
attachment :file
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class BaseModel
|
|
52
|
+
include MongoMapper::Document
|
|
53
|
+
plugin Joint
|
|
54
|
+
attachment :file
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class Image < BaseModel; attachment :image end
|
|
58
|
+
class Video < BaseModel; attachment :video end
|
|
59
|
+
|
|
60
|
+
module JointTestHelpers
|
|
61
|
+
def all_files
|
|
62
|
+
[@file, @image, @image2, @test1, @test2]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def rewind_files
|
|
66
|
+
all_files.each { |file| file.rewind }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def open_file(name)
|
|
70
|
+
File.open(File.join(File.dirname(__FILE__), 'fixtures', name), 'r')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def grid
|
|
74
|
+
@grid ||= Mongo::Grid.new(MongoMapper.database)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def key_names
|
|
78
|
+
[:id, :name, :type, :size]
|
|
79
|
+
end
|
|
40
80
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'helper'
|
|
2
|
+
|
|
3
|
+
class IOTest < Test::Unit::TestCase
|
|
4
|
+
context "#initialize" do
|
|
5
|
+
should "set attributes from hash" do
|
|
6
|
+
Joint::IO.new(:name => 'foo').name.should == 'foo'
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
should "default type to plain text" do
|
|
11
|
+
Joint::IO.new.type.should == 'plain/text'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
should "default size to content size" do
|
|
15
|
+
content = 'This is my content'
|
|
16
|
+
Joint::IO.new(:content => content).size.should == content.size
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
should "alias path to name" do
|
|
20
|
+
Joint::IO.new(:name => 'foo').path.should == 'foo'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "#read" do
|
|
24
|
+
should "return content" do
|
|
25
|
+
Joint::IO.new(:content => 'Testing').read.should == 'Testing'
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/test/test_joint.rb
CHANGED
|
@@ -1,45 +1,5 @@
|
|
|
1
1
|
require 'helper'
|
|
2
2
|
|
|
3
|
-
class Asset
|
|
4
|
-
include MongoMapper::Document
|
|
5
|
-
plugin Joint
|
|
6
|
-
|
|
7
|
-
key :title, String
|
|
8
|
-
attachment :image
|
|
9
|
-
attachment :file
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
class BaseModel
|
|
13
|
-
include MongoMapper::Document
|
|
14
|
-
plugin Joint
|
|
15
|
-
attachment :file
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
class Image < BaseModel; attachment :image end
|
|
19
|
-
class Video < BaseModel; attachment :video end
|
|
20
|
-
|
|
21
|
-
module JointTestHelpers
|
|
22
|
-
def all_files
|
|
23
|
-
[@file, @image, @image2, @test1, @test2]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def rewind_files
|
|
27
|
-
all_files.each { |file| file.rewind }
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def open_file(name)
|
|
31
|
-
File.open(File.join(File.dirname(__FILE__), 'fixtures', name), 'r')
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def grid
|
|
35
|
-
@grid ||= Mongo::Grid.new(MongoMapper.database)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def key_names
|
|
39
|
-
[:id, :name, :type, :size]
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
3
|
class JointTest < Test::Unit::TestCase
|
|
44
4
|
include JointTestHelpers
|
|
45
5
|
|
|
@@ -56,6 +16,43 @@ class JointTest < Test::Unit::TestCase
|
|
|
56
16
|
all_files.each { |file| file.close }
|
|
57
17
|
end
|
|
58
18
|
|
|
19
|
+
context ".name" do
|
|
20
|
+
should "return original_filename" do
|
|
21
|
+
def @image.original_filename
|
|
22
|
+
'frank.jpg'
|
|
23
|
+
end
|
|
24
|
+
Joint.name(@image).should == 'frank.jpg'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
should "fall back to File.basename" do
|
|
28
|
+
Joint.name(@image).should == 'mr_t.jpg'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context ".size" do
|
|
33
|
+
should "return size" do
|
|
34
|
+
def @image.size
|
|
35
|
+
25
|
|
36
|
+
end
|
|
37
|
+
Joint.size(@image).should == 25
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
should "fall back to File.size" do
|
|
41
|
+
Joint.size(@image).should == 13661
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context ".type" do
|
|
46
|
+
should "return type if Joint::Io instance" do
|
|
47
|
+
file = Joint::IO.new(:type => 'image/jpeg')
|
|
48
|
+
Joint.type(@image).should == 'image/jpeg'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
should "fall back to Wand" do
|
|
52
|
+
Joint.type(@image).should == 'image/jpeg'
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
59
56
|
context "Using Joint plugin" do
|
|
60
57
|
should "add each attachment to attachment_names" do
|
|
61
58
|
Asset.attachment_names.should == Set.new([:image, :file])
|
|
@@ -343,4 +340,53 @@ class JointTest < Test::Unit::TestCase
|
|
|
343
340
|
model.should be_valid
|
|
344
341
|
end
|
|
345
342
|
end
|
|
343
|
+
|
|
344
|
+
context "Assigning joint io instance" do
|
|
345
|
+
setup do
|
|
346
|
+
io = Joint::IO.new({
|
|
347
|
+
:name => 'foo.txt',
|
|
348
|
+
:type => 'plain/text',
|
|
349
|
+
:content => 'This is my stuff',
|
|
350
|
+
:size => 19,
|
|
351
|
+
})
|
|
352
|
+
@asset = Asset.create(:file => io)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
should "work" do
|
|
356
|
+
@asset.file_name.should == 'foo.txt'
|
|
357
|
+
@asset.file_size.should == 19
|
|
358
|
+
@asset.file_type.should == 'plain/text'
|
|
359
|
+
@asset.file.read.should == 'This is my stuff'
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
context "A font file" do
|
|
364
|
+
setup do
|
|
365
|
+
@file = open_file('font.eot')
|
|
366
|
+
@doc = Asset.create(:file => @file)
|
|
367
|
+
end
|
|
368
|
+
subject { @doc }
|
|
369
|
+
|
|
370
|
+
should "assign joint keys" do
|
|
371
|
+
subject.file_size.should == 17610
|
|
372
|
+
subject.file_type.should == "application/octet-stream"
|
|
373
|
+
subject.file_id.should_not be_nil
|
|
374
|
+
subject.file_id.should be_instance_of(BSON::ObjectId)
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
context "A music file" do
|
|
379
|
+
setup do
|
|
380
|
+
@file = open_file('example.m4r')
|
|
381
|
+
@doc = Asset.create(:file => @file)
|
|
382
|
+
end
|
|
383
|
+
subject { @doc }
|
|
384
|
+
|
|
385
|
+
should "assign joint keys" do
|
|
386
|
+
subject.file_size.should == 50790
|
|
387
|
+
subject.file_type.should == "audio/mp4"
|
|
388
|
+
subject.file_id.should_not be_nil
|
|
389
|
+
subject.file_id.should be_instance_of(BSON::ObjectId)
|
|
390
|
+
end
|
|
391
|
+
end
|
|
346
392
|
end
|
metadata
CHANGED
|
@@ -6,7 +6,8 @@ version: !ruby/object:Gem::Version
|
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 5
|
|
9
|
-
|
|
9
|
+
- 5
|
|
10
|
+
version: 0.5.5
|
|
10
11
|
platform: ruby
|
|
11
12
|
authors:
|
|
12
13
|
- John Nunemaker
|
|
@@ -14,7 +15,7 @@ autorequire:
|
|
|
14
15
|
bindir: bin
|
|
15
16
|
cert_chain: []
|
|
16
17
|
|
|
17
|
-
date:
|
|
18
|
+
date: 2011-01-22 00:00:00 -05:00
|
|
18
19
|
default_executable:
|
|
19
20
|
dependencies:
|
|
20
21
|
- !ruby/object:Gem::Dependency
|
|
@@ -25,12 +26,11 @@ dependencies:
|
|
|
25
26
|
requirements:
|
|
26
27
|
- - ~>
|
|
27
28
|
- !ruby/object:Gem::Version
|
|
28
|
-
hash:
|
|
29
|
+
hash: 3
|
|
29
30
|
segments:
|
|
30
31
|
- 0
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
version: 0.2.1
|
|
32
|
+
- 4
|
|
33
|
+
version: "0.4"
|
|
34
34
|
type: :runtime
|
|
35
35
|
version_requirements: *id001
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
@@ -114,17 +114,30 @@ extensions: []
|
|
|
114
114
|
extra_rdoc_files: []
|
|
115
115
|
|
|
116
116
|
files:
|
|
117
|
-
-
|
|
117
|
+
- .gitignore
|
|
118
|
+
- Gemfile
|
|
119
|
+
- Gemfile.lock
|
|
120
|
+
- LICENSE
|
|
121
|
+
- README.rdoc
|
|
122
|
+
- Rakefile
|
|
123
|
+
- joint.gemspec
|
|
118
124
|
- lib/joint.rb
|
|
125
|
+
- lib/joint/attachment_proxy.rb
|
|
126
|
+
- lib/joint/class_methods.rb
|
|
127
|
+
- lib/joint/instance_methods.rb
|
|
128
|
+
- lib/joint/io.rb
|
|
129
|
+
- lib/joint/version.rb
|
|
130
|
+
- specs.watchr
|
|
131
|
+
- test/fixtures/example.m4r
|
|
132
|
+
- test/fixtures/font.eot
|
|
119
133
|
- test/fixtures/harmony.png
|
|
120
134
|
- test/fixtures/mr_t.jpg
|
|
121
135
|
- test/fixtures/test1.txt
|
|
122
136
|
- test/fixtures/test2.txt
|
|
123
137
|
- test/fixtures/unixref.pdf
|
|
124
138
|
- test/helper.rb
|
|
139
|
+
- test/joint/test_io.rb
|
|
125
140
|
- test/test_joint.rb
|
|
126
|
-
- LICENSE
|
|
127
|
-
- README.rdoc
|
|
128
141
|
has_rdoc: true
|
|
129
142
|
homepage: http://github.com/jnunemaker/joint
|
|
130
143
|
licenses: []
|
|
@@ -160,10 +173,13 @@ signing_key:
|
|
|
160
173
|
specification_version: 3
|
|
161
174
|
summary: MongoMapper and GridFS joined in file upload love.
|
|
162
175
|
test_files:
|
|
176
|
+
- test/fixtures/example.m4r
|
|
177
|
+
- test/fixtures/font.eot
|
|
163
178
|
- test/fixtures/harmony.png
|
|
164
179
|
- test/fixtures/mr_t.jpg
|
|
165
180
|
- test/fixtures/test1.txt
|
|
166
181
|
- test/fixtures/test2.txt
|
|
167
182
|
- test/fixtures/unixref.pdf
|
|
168
183
|
- test/helper.rb
|
|
184
|
+
- test/joint/test_io.rb
|
|
169
185
|
- test/test_joint.rb
|