joint 0.5.1 → 0.5.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/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem 'i18n'
3
+ gem 'i18n', '0.4.2'
4
4
  gem 'bson_ext', '~> 1.1', :require => false
5
5
  gemspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- joint (0.5)
4
+ joint (0.5.1)
5
5
  mime-types
6
6
  mongo_mapper (~> 0.8.6)
7
7
  wand (~> 0.3)
@@ -37,7 +37,7 @@ PLATFORMS
37
37
 
38
38
  DEPENDENCIES
39
39
  bson_ext (~> 1.1)
40
- i18n
40
+ i18n (= 0.4.2)
41
41
  jnunemaker-matchy
42
42
  joint!
43
43
  mime-types
@@ -3,150 +3,38 @@ 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
- module ClassMethods
15
- def attachment_accessor_module
16
- @attachment_accessor_module ||= Module.new
17
- end
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, :original_filename => Joint.file_name(file)))
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
- module InstanceMethods
63
- def grid
64
- @grid ||= Mongo::Grid.new(database)
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
- class AttachmentProxy
116
- def initialize(instance, name)
117
- @instance, @name = instance, name
28
+ def self.type(file)
29
+ if file.respond_to?(:content_type)
30
+ file.content_type
31
+ else
32
+ Wand.wave(file.path, :original_filename => Joint.name(file))
118
33
  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
147
- end
148
-
149
- def self.file_name(file)
150
- file.respond_to?(:original_filename) ? file.original_filename : File.basename(file.path)
151
34
  end
152
35
  end
36
+
37
+ require 'joint/class_methods'
38
+ require 'joint/instance_methods'
39
+ require 'joint/attachment_proxy'
40
+ require 'joint/io'
@@ -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
@@ -0,0 +1,14 @@
1
+ module Joint
2
+ class IO
3
+ attr_accessor :name, :content, :content_type, :size
4
+
5
+ def initialize(attrs={})
6
+ attrs.each { |key, value| send("#{key}=", value) }
7
+ @content_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
@@ -1,3 +1,3 @@
1
1
  module Joint
2
- Version = '0.5.1'
2
+ Version = '0.5.2'
3
3
  end
@@ -1,16 +1,3 @@
1
- def growl(title, msg, img)
2
- %x{growlnotify -m #{ msg.inspect} -t #{title.inspect} --image ~/.watchr/#{img}.png}
3
- end
4
-
5
- def form_growl_message(str)
6
- results = str.split("\n").last
7
- if results =~ /[1-9]\s(failure|error)s?/
8
- growl "Test Results", "#{results}", "fail"
9
- elsif results != ""
10
- growl "Test Results", "#{results}", "pass"
11
- end
12
- end
13
-
14
1
  def run(cmd)
15
2
  puts(cmd)
16
3
  output = ""
@@ -21,7 +8,7 @@ def run(cmd)
21
8
  $stdout.flush
22
9
  end
23
10
  end
24
- form_growl_message output
11
+ output
25
12
  end
26
13
 
27
14
  def run_test_file(file)
@@ -37,7 +24,7 @@ def related_test_files(path)
37
24
  end
38
25
 
39
26
  watch('test/test_helper\.rb') { system('clear'); run_all_tests }
40
- watch('test/test_.*\.rb') { |m| system('clear'); run_test_file(m[0]) }
27
+ watch('test/.*test_.*\.rb') { |m| system('clear'); run_test_file(m[0]) }
41
28
  watch('lib/.*') { |m| related_test_files(m[0]).each { |file| run_test_file(file) } }
42
29
 
43
30
  # Ctrl-\
@@ -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 content_type to plain text" do
11
+ Joint::IO.new.content_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
@@ -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,45 @@ 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" do
47
+ def @image.content_type
48
+ 'plain/text'
49
+ end
50
+ Joint.type(@image).should == 'plain/text'
51
+ end
52
+
53
+ should "fall back to Wand" do
54
+ Joint.type(@image).should == 'image/jpeg'
55
+ end
56
+ end
57
+
59
58
  context "Using Joint plugin" do
60
59
  should "add each attachment to attachment_names" do
61
60
  Asset.attachment_names.should == Set.new([:image, :file])
@@ -343,4 +342,23 @@ class JointTest < Test::Unit::TestCase
343
342
  model.should be_valid
344
343
  end
345
344
  end
345
+
346
+ context "Assigning joint io instance" do
347
+ setup do
348
+ io = Joint::IO.new({
349
+ :name => 'foo.txt',
350
+ :content_type => 'plain/text',
351
+ :content => 'This is my stuff',
352
+ :size => 19,
353
+ })
354
+ @asset = Asset.create(:file => io)
355
+ end
356
+
357
+ should "work" do
358
+ @asset.file_name.should == 'foo.txt'
359
+ @asset.file_size.should == 19
360
+ @asset.file_type.should == 'plain/text'
361
+ @asset.file.read.should == 'This is my stuff'
362
+ end
363
+ end
346
364
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joint
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 1
10
- version: 0.5.1
9
+ - 2
10
+ version: 0.5.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - John Nunemaker
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-20 00:00:00 -05:00
18
+ date: 2010-12-30 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -122,6 +122,10 @@ files:
122
122
  - Rakefile
123
123
  - joint.gemspec
124
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
125
129
  - lib/joint/version.rb
126
130
  - specs.watchr
127
131
  - test/fixtures/harmony.png
@@ -130,6 +134,7 @@ files:
130
134
  - test/fixtures/test2.txt
131
135
  - test/fixtures/unixref.pdf
132
136
  - test/helper.rb
137
+ - test/joint/test_io.rb
133
138
  - test/test_joint.rb
134
139
  has_rdoc: true
135
140
  homepage: http://github.com/jnunemaker/joint
@@ -172,4 +177,5 @@ test_files:
172
177
  - test/fixtures/test2.txt
173
178
  - test/fixtures/unixref.pdf
174
179
  - test/helper.rb
180
+ - test/joint/test_io.rb
175
181
  - test/test_joint.rb