progstr-filer 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ Progstr Filer is a developer-friendly file hosting platform built specifically for web apps. It lets you easily associate file attachments with your ActiveRecord models and removes the hassle of actually hosting the files yourself.
2
+
3
+ ### Setting up the Ruby gem
4
+
5
+ Bundler makes that all too easy - add this line to your `Gemfile` to have the gem pulled into your app and required automatically.
6
+
7
+
8
+ gem "progstr-filer", :require => "progstr-filer"
9
+
10
+
11
+ ### Credentials
12
+
13
+ Progstr Filer uses two keys similar to Amazon's cloud services. The access key is a public string that gets rendered publicly in URL's and web pages. We use it to identify your account. The secret key is used to sign and encrypt sensitive data. You should keep it, well, secret.
14
+
15
+ Provisioning your add-on with Heroku gets you two environment variables: `PROGSTR_FILER_ACCESS_KEY` and `PROGSTR_FILER_SECRET_KEY`. Add those to your `config/environments/production.rb` file:
16
+
17
+ Progstr::Filer.access_key = ENV['PROGSTR_FILER_ACCESS_KEY']
18
+ Progstr::Filer.secret_key = ENV['PROGSTR_FILER_SECRET_KEY']
19
+
20
+
21
+ ### Defining an uploader
22
+
23
+ Every attachment can have a specific set of options that take effect while uploading and manipulating it. Those settings get configured via your own class that will extend `Progstr::Filer::Uploader`. You could store uploader classes in your `app/uploaders` folder. Here is a sample class:
24
+
25
+ class AvatarUploader < Progstr::Filer::Uploader
26
+ #uploader options
27
+ end
28
+
29
+
30
+ ### Associating uploaders with your models
31
+
32
+ Progstr Filer extends ActiveRecord models and lets you use the `has_file` method in class definitions. Here is a User model class that has an avatar image managed as a Progstr Filer attachment via its `avatar` property:
33
+
34
+ class User < ActiveRecord::Base
35
+ has_file :avatar, AvatarUploader
36
+ end
37
+
38
+
39
+ Note: make sure your database table has an `avatar` column created already. Future versions of the `progstr-filer` gem will let you generate migrations automatically.
40
+
41
+ ### Feeding data to your uploaders
42
+
43
+ That is easy - all you need is assign a Ruby File object to the uploader property and save the model object:
44
+
45
+ @user.avatar = uploaded_image_file
46
+ @user.avatar.save
47
+
48
+
49
+ Rails can get most of the job done for you automatically if you create a file upload form:
50
+
51
+ <div class="field">
52
+ <%= f.label :avatar %>
53
+ <%= f.file_field :avatar %>
54
+ </div>
55
+
56
+
57
+ ...and create your model from the params hash:
58
+
59
+ @user = User.new(params[:user])
60
+ @user.save
61
+
62
+
63
+ ### Generating URLs for files
64
+
65
+ Just use the `url` method on your attachments, say `@user.avatar.url`. Here is a sample view that generates an `img` tag pointing to the avatar image:
66
+
67
+ <p>
68
+ <b>Avatar:</b><br>
69
+ <%= image_tag @user.avatar.url, :style => "max-width: 600px; margin: 10px 0px;" %>
70
+ </p>
71
+
72
+ ### Validation
73
+
74
+ Users may upload all types of files to your application and it might be a good idea to restrict that to the set of files that your application knows how to process. For example it would not be a good idea to allow non-image file types as an avatar picture. It might be a good idea to disable executable content that might spread malware too. To help with that the `progstr-filer` gem currently supports attachment validation according to an extension whitelist through the `validates_file_extension_of` method that is available to model objects:
75
+
76
+ class User < ActiveRecord::Base
77
+ has_file :avatar, AvatarUploader
78
+ validates_file_extension_of :avatar, :allowed => ["jpg", "png"]
79
+ end
80
+
81
+ In addition you can restrict the file size using `validates_file_size_of`:
82
+
83
+ class User < ActiveRecord::Base
84
+ has_file :avatar, AvatarUploader
85
+ validates_file_size_of :avatar, :less_than => 1 * 1024 * 1024
86
+ end
87
+
88
+ The example above will not allow files larger than 1 MB. You can specify a lower bound using the `:greater_than` option or even pass a numeric range using the `:in` option.
89
+
90
+ Of course, requiring users to always upload a file when saving a model object, use the Rails built-in `validates_presence_of` validator:
91
+
92
+ class User < ActiveRecord::Base
93
+ has_file :avatar, AvatarUploader
94
+ validates_presence_of :avatar
95
+ end
96
+
97
+ You can pass a custom error message for all validators using the `:message` option.
98
+
99
+ ### Deleting stale files
100
+
101
+ Every time you set a new file and save your model, the old file will get scheduled for deletion. The same happens when you `destroy` your model. Note that calling `delete` for your model will not delete any associated files.
102
+
103
+ ### Source code
104
+
105
+ The `progstr-filer` [gem](https://rubygems.org/gems/progstr-filer) is open source and its code is hosted on [Github](https://github.com/progstr/progstr-filer-gem).
106
+
107
+ All the techniques outlined in this document are available as a fully-functional Rails project on [Github](https://github.com/progstr/progstr-filer-demo) too.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.1
1
+ 0.8.2
@@ -23,12 +23,6 @@ module Progstr
23
23
  def #{attribute}=(new_file)
24
24
  _set_attachment(:#{attribute}, new_file)
25
25
  end
26
- def #{attribute}_file_size
27
- _get_attachment(:#{attribute}).size
28
- end
29
- def #{attribute}_file_extension
30
- _get_attachment(:#{attribute}).extension
31
- end
32
26
  def upload_#{attribute}!
33
27
  _upload_attachment(:#{attribute})
34
28
  end
@@ -1,7 +1,7 @@
1
1
  module Progstr
2
2
  module Filer
3
3
  class Attachment
4
- attr_accessor :id, :attribute, :file
4
+ attr_accessor :id, :attribute, :file, :pre_validated
5
5
 
6
6
  @@id_generator = ::UUID.new
7
7
 
@@ -31,7 +31,9 @@ module Progstr
31
31
  result = Attachment.new
32
32
  result.id = generate_id
33
33
  result.attribute = attribute
34
+
34
35
  result.file = file
36
+ result.pre_validated = false
35
37
  result
36
38
  end
37
39
 
@@ -58,6 +60,8 @@ module Progstr
58
60
  result = Attachment.new
59
61
  result.id = id
60
62
  result.attribute = attribute
63
+
64
+ result.pre_validated = true
61
65
  result
62
66
  end
63
67
 
@@ -11,7 +11,7 @@ module Progstr
11
11
 
12
12
  message = options[:message] || "File size not between #{min} and #{max} bytes."
13
13
 
14
- validates_with PropertyValidator, :attributes => [attribute],
14
+ validates_with AttachmentPropertyValidator, :attributes => [attribute],
15
15
  :property => :size,
16
16
  :in => allowed_range,
17
17
  :message => message,
@@ -23,7 +23,7 @@ module Progstr
23
23
  allowed = options[:allowed] || EverythingIncluded.new
24
24
  message = options[:message] || "File extension not allowed."
25
25
 
26
- validates_with PropertyValidator, :attributes => [attribute],
26
+ validates_with AttachmentPropertyValidator, :attributes => [attribute],
27
27
  :property => :extension,
28
28
  :in => allowed,
29
29
  :message => message
@@ -35,15 +35,17 @@ module Progstr
35
35
  end
36
36
  end
37
37
 
38
- class PropertyValidator < ActiveModel::Validations::InclusionValidator
38
+ class AttachmentPropertyValidator < ActiveModel::Validations::InclusionValidator
39
39
  def initialize(options)
40
40
  @property = options[:property]
41
41
  super(options)
42
42
  end
43
43
 
44
- def validate_each(record, attribute, value)
45
- property_value = value.send(@property)
46
- super(record, attribute, property_value) unless value.nil? || value.blank? || property_value.nil?
44
+ def validate_each(record, attribute, attachment)
45
+ unless attachment.pre_validated
46
+ property_value = attachment.send(@property)
47
+ super(record, attribute, property_value) unless attachment.nil? || attachment.blank? || property_value.nil?
48
+ end
47
49
  end
48
50
  end
49
51
  end
Binary file
@@ -46,6 +46,20 @@ class TestValidation < UserTest
46
46
  assert_equal u.errors[:avatar], ["Avatar image extension not allowed."]
47
47
  end
48
48
 
49
+ test "don't validate prevalidated attachments on record update" do
50
+ u = ValidatedUser.new
51
+ u.name = "John"
52
+ avatar = File.open("test/adium-green-duckling.png")
53
+ u.avatar = avatar
54
+ save_success = u.save
55
+ assert_true save_success, "Initially valid."
56
+
57
+ loaded = ValidatedUser.find(u.id)
58
+ loaded.name = "Jim"
59
+ save_success = loaded.save
60
+ assert_true save_success, "Still valid on update when attachment not modified."
61
+ end
62
+
49
63
  test "validation passes" do
50
64
  u = ValidatedUser.new
51
65
  jpg = FileLike.new
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: progstr-filer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-06 00:00:00.000000000Z
12
+ date: 2012-01-12 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
- requirement: &24667240 !ruby/object:Gem::Requirement
16
+ requirement: &14664400 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *24667240
24
+ version_requirements: *14664400
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activemodel
27
- requirement: &24665880 !ruby/object:Gem::Requirement
27
+ requirement: &14662460 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.0.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *24665880
35
+ version_requirements: *14662460
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: uuid
38
- requirement: &24663920 !ruby/object:Gem::Requirement
38
+ requirement: &14658240 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *24663920
46
+ version_requirements: *14658240
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rest-client
49
- requirement: &24663080 !ruby/object:Gem::Requirement
49
+ requirement: &14657280 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *24663080
57
+ version_requirements: *14657280
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: multi_json
60
- requirement: &24659740 !ruby/object:Gem::Requirement
60
+ requirement: &14656740 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *24659740
68
+ version_requirements: *14656740
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
- requirement: &24659000 !ruby/object:Gem::Requirement
71
+ requirement: &14655880 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *24659000
79
+ version_requirements: *14655880
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: guard-test
82
- requirement: &24658260 !ruby/object:Gem::Requirement
82
+ requirement: &14655200 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *24658260
90
+ version_requirements: *14655200
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rb-inotify
93
- requirement: &24657380 !ruby/object:Gem::Requirement
93
+ requirement: &14654400 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *24657380
101
+ version_requirements: *14654400
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: libnotify
104
- requirement: &24656540 !ruby/object:Gem::Requirement
104
+ requirement: &14653640 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *24656540
112
+ version_requirements: *14653640
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: shoulda
115
- requirement: &24652860 !ruby/object:Gem::Requirement
115
+ requirement: &14652960 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *24652860
123
+ version_requirements: *14652960
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: bundler
126
- requirement: &24651640 !ruby/object:Gem::Requirement
126
+ requirement: &14652280 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ~>
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: 1.0.0
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *24651640
134
+ version_requirements: *14652280
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: jeweler
137
- requirement: &24648740 !ruby/object:Gem::Requirement
137
+ requirement: &14648520 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ~>
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: 1.6.4
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *24648740
145
+ version_requirements: *14648520
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: rcov
148
- requirement: &24647720 !ruby/object:Gem::Requirement
148
+ requirement: &14647220 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ! '>='
@@ -153,10 +153,10 @@ dependencies:
153
153
  version: '0'
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *24647720
156
+ version_requirements: *14647220
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: rdoc
159
- requirement: &24646940 !ruby/object:Gem::Requirement
159
+ requirement: &14646360 !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
162
162
  - - ! '>='
@@ -164,7 +164,7 @@ dependencies:
164
164
  version: '0'
165
165
  type: :development
166
166
  prerelease: false
167
- version_requirements: *24646940
167
+ version_requirements: *14646360
168
168
  description: Progstr Filer is a developer-friendly file and attachment hosting service
169
169
  that lets you easily build apps that store and share files.
170
170
  email: hristo@deshev.com
@@ -172,7 +172,7 @@ executables: []
172
172
  extensions: []
173
173
  extra_rdoc_files:
174
174
  - LICENSE.txt
175
- - README.rdoc
175
+ - README.md
176
176
  files:
177
177
  - .document
178
178
  - .rspec
@@ -180,7 +180,7 @@ files:
180
180
  - Gemfile.lock
181
181
  - Guardfile
182
182
  - LICENSE.txt
183
- - README.rdoc
183
+ - README.md
184
184
  - Rakefile
185
185
  - VERSION
186
186
  - lib/filer/activerecord.rb
@@ -190,6 +190,7 @@ files:
190
190
  - lib/filer/uploader.rb
191
191
  - lib/filer/validation.rb
192
192
  - lib/progstr-filer.rb
193
+ - test/adium-green-duckling.png
193
194
  - test/file_like.rb
194
195
  - test/test_attachment_url.rb
195
196
  - test/test_file_mount.rb
@@ -214,7 +215,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
214
215
  version: '0'
215
216
  segments:
216
217
  - 0
217
- hash: 1683985428954431553
218
+ hash: 4163702518948381072
218
219
  required_rubygems_version: !ruby/object:Gem::Requirement
219
220
  none: false
220
221
  requirements:
data/README.rdoc DELETED
@@ -1,19 +0,0 @@
1
- = filer-gem
2
-
3
- Description goes here.
4
-
5
- == Contributing to filer-gem
6
-
7
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
- * Fork the project
10
- * Start a feature/bugfix branch
11
- * Commit and push until you are happy with your contribution
12
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
-
15
- == Copyright
16
-
17
- Copyright (c) 2011 Hristo Deshev. See LICENSE.txt for
18
- further details.
19
-