oscillator 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  require 'oscillator/version'
2
- require 'oscillator/file_size_validator'
3
- require 'oscillator/canonical_uploader_path'
2
+ require 'oscillator/validations'
3
+ require 'oscillator/file_location_resolver'
4
4
 
5
5
  module Oscillator
6
6
  end
@@ -0,0 +1,11 @@
1
+ module Oscillator
2
+ module FileLocationResolver
3
+ def filename
4
+ "#{mounted_as}.#{file.extension.downcase}" if @filename
5
+ end
6
+
7
+ def store_dir
8
+ "#{model.class.name.underscore}/#{model.id}"
9
+ end
10
+ end
11
+ end
@@ -1,68 +1,70 @@
1
- # lib/file_size_validator.rb
2
1
  # Based on: https://gist.github.com/795665
2
+ require 'singleton'
3
3
 
4
- class FileSizeValidator < ActiveModel::EachValidator
5
- MESSAGES = { :is => :wrong_size, :minimum => :size_too_small, :maximum => :size_too_big }.freeze
6
- CHECKS = { :is => :==, :minimum => :>=, :maximum => :<= }.freeze
4
+ module Oscillator
5
+ class FileSizeValidator < ActiveModel::EachValidator
6
+ MESSAGES = { :is => :wrong_size, :minimum => :size_too_small, :maximum => :size_too_big }.freeze
7
+ CHECKS = { :is => :==, :minimum => :>=, :maximum => :<= }.freeze
7
8
 
8
- DEFAULT_TOKENIZER = lambda { |value| value.split(//) }
9
- RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :tokenizer, :too_short, :too_long]
9
+ DEFAULT_TOKENIZER = lambda { |value| value.split(//) }
10
+ RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :tokenizer, :too_short, :too_long]
10
11
 
11
- def initialize(options)
12
- if range = (options.delete(:in) || options.delete(:within))
13
- raise ArgumentError, ":in and :within must be a Range" unless range.is_a?(Range)
14
- options[:minimum], options[:maximum] = range.begin, range.end
15
- options[:maximum] -= 1 if range.exclude_end?
16
- end
12
+ def initialize(options)
13
+ if range = (options.delete(:in) || options.delete(:within))
14
+ raise ArgumentError, ":in and :within must be a Range" unless range.is_a?(Range)
15
+ options[:minimum], options[:maximum] = range.begin, range.end
16
+ options[:maximum] -= 1 if range.exclude_end?
17
+ end
17
18
 
18
- super
19
- end
19
+ super
20
+ end
20
21
 
21
- def check_validity!
22
- keys = CHECKS.keys & options.keys
22
+ def check_validity!
23
+ keys = CHECKS.keys & options.keys
23
24
 
24
- if keys.empty?
25
- raise ArgumentError, 'Range unspecified. Specify the :within, :maximum, :minimum, or :is option.'
26
- end
25
+ if keys.empty?
26
+ raise ArgumentError, 'Range unspecified. Specify the :within, :maximum, :minimum, or :is option.'
27
+ end
27
28
 
28
- keys.each do |key|
29
- value = options[key]
29
+ keys.each do |key|
30
+ value = options[key]
30
31
 
31
- unless value.is_a?(Integer) && value >= 0
32
- raise ArgumentError, ":#{key} must be a nonnegative Integer"
32
+ unless value.is_a?(Integer) && value >= 0
33
+ raise ArgumentError, ":#{key} must be a nonnegative Integer"
34
+ end
33
35
  end
34
36
  end
35
- end
36
37
 
37
- def validate_each(record, attribute, value)
38
- raise(ArgumentError, "A CarrierWave::Uploader::Base object was expected") unless value.kind_of? CarrierWave::Uploader::Base
38
+ def validate_each(record, attribute, value)
39
+ raise(ArgumentError, "A CarrierWave::Uploader::Base object was expected") unless value.kind_of? CarrierWave::Uploader::Base
39
40
 
40
- value = (options[:tokenizer] || DEFAULT_TOKENIZER).call(value) if value.kind_of?(String)
41
+ value = (options[:tokenizer] || DEFAULT_TOKENIZER).call(value) if value.kind_of?(String)
41
42
 
42
- CHECKS.each do |key, validity_check|
43
- next unless check_value = options[key]
43
+ CHECKS.each do |key, validity_check|
44
+ next unless check_value = options[key]
44
45
 
45
- value ||= [] if key == :maximum
46
+ value ||= [] if key == :maximum
46
47
 
47
- value_size = value.size
48
- next if value_size.send(validity_check, check_value)
48
+ value_size = value.size
49
+ next if value_size.send(validity_check, check_value)
49
50
 
50
- errors_options = options.except(*RESERVED_OPTIONS)
51
- errors_options[:file_size] = help.number_to_human_size check_value
51
+ errors_options = options.except(*RESERVED_OPTIONS)
52
+ errors_options[:file_size] = help.number_to_human_size check_value
52
53
 
53
- default_message = options[MESSAGES[key]]
54
- errors_options[:message] ||= default_message if default_message
54
+ default_message = options[MESSAGES[key]]
55
+ errors_options[:message] ||= default_message if default_message
55
56
 
56
- record.errors.add(attribute, MESSAGES[key], errors_options)
57
+ record.errors.add(attribute, MESSAGES[key], errors_options)
58
+ end
57
59
  end
58
- end
59
60
 
60
- def help
61
- Helper.instance
62
- end
61
+ def help
62
+ Helper.instance
63
+ end
63
64
 
64
- class Helper
65
- include Singleton
66
- include ActionView::Helpers::NumberHelper
65
+ class Helper
66
+ include ::Singleton
67
+ include ::ActionView::Helpers::NumberHelper
68
+ end
67
69
  end
68
70
  end
@@ -0,0 +1 @@
1
+ require 'oscillator/file_size_validator'
@@ -1,3 +1,3 @@
1
1
  module Oscillator
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ class ResolvableUploader < CarrierWave::Uploader::Base
4
+ include Oscillator::FileLocationResolver
5
+ end
6
+
7
+ class MyModel
8
+ def id
9
+ 123
10
+ end
11
+ end
12
+
13
+ describe Oscillator::FileLocationResolver, :carrier_wave do
14
+ let(:model) { MyModel.new }
15
+ let(:uploader) { ResolvableUploader.new model, :resolver }
16
+
17
+ describe '#filename' do
18
+ context 'when a file has been stored' do
19
+ before { uploader.store! File.open(@test_image_directory + 'SMALL-LOGO-SHORT-AND-WIDE.PNG') }
20
+
21
+ it 'is the mounted as name along with the lowercase file extension' do
22
+ uploader.filename.should eql 'resolver.png'
23
+ end
24
+ end
25
+
26
+ context 'when a file has not been stored' do
27
+ it 'is nil' do
28
+ uploader.filename.should be_nil
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#store_dir' do
34
+ it 'is the underscored class name followed by a subfolder for the ID of the model' do
35
+ uploader.store_dir.should eql 'my_model/123'
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+
3
+ class ImageUploader < CarrierWave::Uploader::Base
4
+ end
5
+
6
+ class ValidatableClassWithMinimum
7
+ include ActiveModel::Validations
8
+ extend CarrierWave::Mount
9
+
10
+ attr_accessor :image
11
+
12
+ mount_uploader :image
13
+
14
+ validates :image,
15
+ :'oscillator/file_size' => {
16
+ minimum: 2 }
17
+ end
18
+
19
+ class ValidatableClassWithMaximum
20
+ include ActiveModel::Validations
21
+ extend CarrierWave::Mount
22
+
23
+ attr_accessor :image
24
+
25
+ mount_uploader :image
26
+
27
+ validates :image,
28
+ :'oscillator/file_size' => {
29
+ maximum: 2 }
30
+ end
31
+
32
+ class ValidatableClassWithWithin
33
+ include ActiveModel::Validations
34
+ extend CarrierWave::Mount
35
+
36
+ attr_accessor :image
37
+
38
+ mount_uploader :image
39
+
40
+ validates :image,
41
+ :'oscillator/file_size' => {
42
+ within: 2..4 }
43
+ end
44
+
45
+ class ValidatableClassWithIs
46
+ include ActiveModel::Validations
47
+ extend CarrierWave::Mount
48
+
49
+ attr_accessor :image
50
+
51
+ mount_uploader :image
52
+
53
+ validates :image,
54
+ :'oscillator/file_size' => {
55
+ is: 2 }
56
+ end
57
+
58
+ describe Oscillator::FileSizeValidator, :carrier_wave do
59
+ describe '#valid?' do
60
+ context 'when a `minimum` is set' do
61
+ let(:validatable) { ValidatableClassWithMinimum.new }
62
+
63
+ context 'and a file lower than the minimum is stored' do
64
+ before { validatable.image.store! File.open(@test_image_directory + '0-byte-file.txt') }
65
+
66
+ it 'is false' do
67
+ validatable.should_not be_valid
68
+ end
69
+ end
70
+
71
+ context 'and a file the same as the minimum is stored' do
72
+ before { validatable.image.store! File.open(@test_image_directory + '2-byte-file.txt') }
73
+
74
+ it 'is true' do
75
+ validatable.should be_valid
76
+ end
77
+ end
78
+ end
79
+
80
+ context 'when a `maximum` is set' do
81
+ let(:validatable) { ValidatableClassWithMaximum.new }
82
+
83
+ context 'and a file higher than the maximum is stored' do
84
+ before { validatable.image.store! File.open(@test_image_directory + '3-byte-file.txt') }
85
+
86
+ it 'is false' do
87
+ validatable.should_not be_valid
88
+ end
89
+ end
90
+
91
+ context 'and a file the same as the maximum is stored' do
92
+ before { validatable.image.store! File.open(@test_image_directory + '2-byte-file.txt') }
93
+
94
+ it 'is true' do
95
+ validatable.should be_valid
96
+ end
97
+ end
98
+ end
99
+
100
+ context 'when a `within` range is set' do
101
+ let(:validatable) { ValidatableClassWithWithin.new }
102
+
103
+ context 'and a file below the bottom of the range is stored' do
104
+ before { validatable.image.store! File.open(@test_image_directory + '0-byte-file.txt') }
105
+
106
+ it 'is false' do
107
+ validatable.should_not be_valid
108
+ end
109
+ end
110
+
111
+ context 'and a file at the bottom of the range is stored' do
112
+ before { validatable.image.store! File.open(@test_image_directory + '2-byte-file.txt') }
113
+
114
+ it 'is true' do
115
+ validatable.should be_valid
116
+ end
117
+ end
118
+
119
+ context 'and a file at the top of the range is stored' do
120
+ before { validatable.image.store! File.open(@test_image_directory + '4-byte-file.txt') }
121
+
122
+ it 'is true' do
123
+ validatable.should be_valid
124
+ end
125
+ end
126
+
127
+ context 'and a file above the top of the range is stored' do
128
+ before { validatable.image.store! File.open(@test_image_directory + '5-byte-file.txt') }
129
+
130
+ it 'is false' do
131
+ validatable.should_not be_valid
132
+ end
133
+ end
134
+ end
135
+
136
+ context 'when `is` is set' do
137
+ let(:validatable) { ValidatableClassWithIs.new }
138
+
139
+ context 'and a file below the bottom of the range is stored' do
140
+ before { validatable.image.store! File.open(@test_image_directory + '0-byte-file.txt') }
141
+
142
+ it 'is false' do
143
+ validatable.should_not be_valid
144
+ end
145
+ end
146
+
147
+ context 'and a file that is the exact size is stored' do
148
+ before { validatable.image.store! File.open(@test_image_directory + '2-byte-file.txt') }
149
+
150
+ it 'is true' do
151
+ validatable.should be_valid
152
+ end
153
+ end
154
+
155
+ context 'and a file above the top of the range is stored' do
156
+ before { validatable.image.store! File.open(@test_image_directory + '3-byte-file.txt') }
157
+
158
+ it 'is false' do
159
+ validatable.should_not be_valid
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
File without changes
@@ -0,0 +1 @@
1
+ a
@@ -0,0 +1 @@
1
+ aa
@@ -0,0 +1 @@
1
+ aaa
@@ -0,0 +1 @@
1
+ aaaa
@@ -0,0 +1,12 @@
1
+ require 'active_model'
2
+ require 'action_view'
3
+ require 'carrierwave'
4
+ require 'oscillator'
5
+
6
+ Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |f| require f }
7
+
8
+ RSpec.configure do |config|
9
+ config.after(:suite) do
10
+ `rm -rf ./my_model`
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ ###
2
+ # Makes CarrierWave tests faster and more reliable
3
+ #
4
+
5
+ CarrierWave.configure do |config|
6
+ config.storage = :file
7
+ config.enable_processing = false
8
+ end
9
+
10
+ RSpec.configure do |config|
11
+ config.before(:each, :carrier_wave => true) do
12
+ @test_image_directory = File.dirname(__FILE__) + '/../fixtures/'
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ RSpec.configure do |config|
2
+ # Configure RSpec to run focused specs, and also respect the alias 'fit' for focused specs
3
+ config.treat_symbols_as_metadata_keys_with_true_values = true
4
+ config.filter_run :focused => true
5
+ config.alias_example_to :fit, :focused => true
6
+ config.run_all_when_everything_filtered = true
7
+ end
@@ -0,0 +1,4 @@
1
+ RSpec.configure do |config|
2
+ # Configure RSpec to respect the alias 'pit' for pending specs
3
+ config.alias_example_to :pit, :pending => true
4
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oscillator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,24 +10,152 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-10-02 00:00:00.000000000 Z
13
+ date: 2012-10-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: activerecord
16
+ name: carrierwave
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: '3.1'
22
+ version: '0.5'
23
23
  type: :runtime
24
24
  prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '0.5'
31
+ - !ruby/object:Gem::Dependency
32
+ name: activemodel
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '3.1'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '3.1'
47
+ - !ruby/object:Gem::Dependency
48
+ name: actionpack
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.1'
55
+ type: :development
56
+ prerelease: false
25
57
  version_requirements: !ruby/object:Gem::Requirement
26
58
  none: false
27
59
  requirements:
28
60
  - - ~>
29
61
  - !ruby/object:Gem::Version
30
62
  version: '3.1'
63
+ - !ruby/object:Gem::Dependency
64
+ name: rspec
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: '2.11'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: '2.11'
79
+ - !ruby/object:Gem::Dependency
80
+ name: fuubar
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
86
+ version: '1.0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ version: '1.0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: guard
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: 1.4.0
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 1.4.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: guard-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ~>
117
+ - !ruby/object:Gem::Version
118
+ version: 2.0.0
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ~>
125
+ - !ruby/object:Gem::Version
126
+ version: 2.0.0
127
+ - !ruby/object:Gem::Dependency
128
+ name: rb-fsevent
129
+ requirement: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ~>
133
+ - !ruby/object:Gem::Version
134
+ version: 0.9.1
135
+ type: :development
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ~>
141
+ - !ruby/object:Gem::Version
142
+ version: 0.9.1
143
+ - !ruby/object:Gem::Dependency
144
+ name: awesome_print
145
+ requirement: !ruby/object:Gem::Requirement
146
+ none: false
147
+ requirements:
148
+ - - ~>
149
+ - !ruby/object:Gem::Version
150
+ version: 1.1.0
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ~>
157
+ - !ruby/object:Gem::Version
158
+ version: 1.1.0
31
159
  description: ''
32
160
  email: support@chirrpy.com
33
161
  executables: []
@@ -36,13 +164,26 @@ extra_rdoc_files:
36
164
  - README.md
37
165
  - LICENSE
38
166
  files:
39
- - lib/oscillator/canonical_uploader_path.rb
167
+ - lib/oscillator/file_location_resolver.rb
40
168
  - lib/oscillator/file_size_validator.rb
169
+ - lib/oscillator/validations.rb
41
170
  - lib/oscillator/version.rb
42
171
  - lib/oscillator.rb
43
172
  - Rakefile
44
173
  - README.md
45
174
  - LICENSE
175
+ - spec/file_location_resolver_spec.rb
176
+ - spec/file_size_validator_spec.rb
177
+ - spec/fixtures/0-byte-file.txt
178
+ - spec/fixtures/2-byte-file.txt
179
+ - spec/fixtures/3-byte-file.txt
180
+ - spec/fixtures/4-byte-file.txt
181
+ - spec/fixtures/5-byte-file.txt
182
+ - spec/fixtures/SMALL-LOGO-SHORT-AND-WIDE.PNG
183
+ - spec/spec_helper.rb
184
+ - spec/support/carrier_wave.rb
185
+ - spec/support/focused.rb
186
+ - spec/support/pending.rb
46
187
  homepage: https://github.com/chirrpy/oscillator
47
188
  licenses: []
48
189
  post_install_message:
@@ -68,4 +209,16 @@ rubygems_version: 1.8.24
68
209
  signing_key:
69
210
  specification_version: 3
70
211
  summary: Shared CarrierWave and Validations and Configurations
71
- test_files: []
212
+ test_files:
213
+ - spec/file_location_resolver_spec.rb
214
+ - spec/file_size_validator_spec.rb
215
+ - spec/fixtures/0-byte-file.txt
216
+ - spec/fixtures/2-byte-file.txt
217
+ - spec/fixtures/3-byte-file.txt
218
+ - spec/fixtures/4-byte-file.txt
219
+ - spec/fixtures/5-byte-file.txt
220
+ - spec/fixtures/SMALL-LOGO-SHORT-AND-WIDE.PNG
221
+ - spec/spec_helper.rb
222
+ - spec/support/carrier_wave.rb
223
+ - spec/support/focused.rb
224
+ - spec/support/pending.rb
@@ -1,9 +0,0 @@
1
- module CanonicalUploaderPath
2
- def filename
3
- "#{mounted_as}.#{file.extension.downcase}" if @filename
4
- end
5
-
6
- def store_dir
7
- "#{model.class.name.underscore}/#{model.id}"
8
- end
9
- end