neofiles 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +1 -0
- data/README.md +417 -0
- data/Rakefile +40 -0
- data/app/assets/images/neofiles/loading.gif +0 -0
- data/app/assets/images/neofiles/swf-thumb-100x100.png +0 -0
- data/app/assets/images/neofiles/watermark.png +0 -0
- data/app/assets/javascripts/neofiles/index.js.coffee +3 -0
- data/app/assets/javascripts/neofiles/jquery.fileupload.js +1128 -0
- data/app/assets/javascripts/neofiles/jquery.iframe-transport.js +172 -0
- data/app/assets/javascripts/neofiles/jquery.neofiles.js.coffee +191 -0
- data/app/assets/stylesheets/neofiles/index.css.scss +3 -0
- data/app/assets/stylesheets/neofiles/neofiles.css.scss +149 -0
- data/app/controllers/concerns/neofiles/not_found.rb +21 -0
- data/app/controllers/neofiles/admin_controller.rb +228 -0
- data/app/controllers/neofiles/admin_test_controller.rb +5 -0
- data/app/controllers/neofiles/files_controller.rb +28 -0
- data/app/controllers/neofiles/images_controller.rb +130 -0
- data/app/helpers/neofiles/neofiles_helper.rb +188 -0
- data/app/models/neofiles/file.rb +319 -0
- data/app/models/neofiles/file_chunk.rb +18 -0
- data/app/models/neofiles/image.rb +119 -0
- data/app/models/neofiles/swf.rb +45 -0
- data/app/views/neofiles/admin/_file_compact.html.haml +85 -0
- data/app/views/neofiles/admin/file_compact.html.haml +1 -0
- data/app/views/neofiles/admin_test/file_compact.erb +7 -0
- data/config/locales/ru.yml +21 -0
- data/config/routes.rb +1 -0
- data/lib/neofiles.rb +94 -0
- data/lib/neofiles/engine.rb +33 -0
- data/lib/neofiles/version.rb +3 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f5872fc7a18fd718ba418406742eff52c13a95f4
|
4
|
+
data.tar.gz: e677b851a4e6b89cb71d87360f22ba22a1488577
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b170149ccb7201d112291695d16fb0595902d4fe180f4e1f8541aab49897f4b149d3c522f825adda3fb91520fb7de7d756169f6d1740665344d9d55126077395
|
7
|
+
data.tar.gz: d0b896968b9be2b52274a0bec910508a9a44004adb5c0b6d8ded9ae7948be2abe4f8af44fd9666117c736c98c198e7c3560e305113d7de05654e42b0bb17ca91
|
data/LICENSE
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Закрытая лицензия
|
data/README.md
ADDED
@@ -0,0 +1,417 @@
|
|
1
|
+
Neofiles
|
2
|
+
========
|
3
|
+
|
4
|
+
Neofiles is a filesystem-like gem for storing and managing files, mainly for organizing attachments to Active Models
|
5
|
+
in Rails applications: avatars, logotypes, product images etc.
|
6
|
+
|
7
|
+
It is simple and powerful, but has some prerequisites. If you accept them it can keep the file management subsystem of
|
8
|
+
your application lightweight and headache-free. If you find yourself fighting it instead of enjoying it, maybe it is not
|
9
|
+
fitted for your task, try switching to more classic alternatives like Paperclip or Carrierwave.
|
10
|
+
|
11
|
+
The classical approach of storing files in a local filesystem and postprocessing them at the moment of upload/save has
|
12
|
+
the following drawbacks:
|
13
|
+
|
14
|
+
1. Hard to copy/backup/shard the entire file set or its part.
|
15
|
+
1. Almost impossible to make batch queries like finding a subset of files by some criteria.
|
16
|
+
1. Complex metadata handling via a companion DB model + usually gems do not provide such functionality, DIY.
|
17
|
+
1. Hard to change postprocessing rules, say when design changes and you need an avatar 20px larger — oops, we need to
|
18
|
+
travel through all the objects and resave originals or thumbnails (if originals are available, of course, which
|
19
|
+
is not always the case).
|
20
|
+
1. The last point naturally leads to another: why at all a model needs to know how its logo must be resized or otherwise
|
21
|
+
postprocessed for the sake of design or whatever? This is completely irrelevant to the model itself and should be
|
22
|
+
defined elsewhere.
|
23
|
+
|
24
|
+
Neofiles addresses these issues in following ways:
|
25
|
+
|
26
|
+
***Database storage***: all files are stored in MongoDB database, thus providing standard (and very efficient)
|
27
|
+
mechanisms for backup, sharding, replication, monitoring & control, you name it. Most importantly, all this is done
|
28
|
+
by standard and well described tools, no need to put tricky cron jobs at night to backup several Gb.
|
29
|
+
|
30
|
+
***File models***: host (owner) models only store IDs of file objects `Neofiles::File` which is actually a metadata
|
31
|
+
container and a handle to real file bytes (a collection of `Neofiles::FileChunk`). The file + chunks concept is called
|
32
|
+
Mongo GridFS.
|
33
|
+
|
34
|
+
***File model is environment agnostic***: it does not know anything about its URL, thumbnail size and similar things.
|
35
|
+
It only stores data and metadata. To actually stream file bytes to clients there is a set of controllers (and of course
|
36
|
+
appropriate routes must be set up).
|
37
|
+
|
38
|
+
***No postprocessing at file save***: the only thing can be done is cropping extremely large images, like resizing
|
39
|
+
them to some max value to avoid storing unnecessarily detailed pics and keep disk & memory usage low.
|
40
|
+
|
41
|
+
***Postprocessing by request***: real job like resizing an avatar to 100x100px thumbnail is done by an HTTP request
|
42
|
+
at runtime, e.g. the real file URL might be `/neofiles/serve-image/ID`, whilst the thumbnail's is
|
43
|
+
`/neofiles/serve-image/ID/100x100` — all this is done in `Neofiles::ImagesController`, dedicated to serving and modifying
|
44
|
+
images. Any special logic for handling videos, audios, pdfs or whatever can be achieved in similar way (you have to code
|
45
|
+
it, only images are supported out of the box).
|
46
|
+
|
47
|
+
***Rely on webserver cache***: to keep things simple and not worry about caches and deleting thumbnails, the image
|
48
|
+
streaming controller always generates a fresh copy of postprocessed original, be it an original with watermarks or
|
49
|
+
a resized thumbnail. The task to cache the result is a burden of frontend webserver, like Nginx.
|
50
|
+
|
51
|
+
***Immutability***: technically, any file content and metadata can be changed, and any file can be completely deleted.
|
52
|
+
But deleting is useless as MongoDB does not reallocate deleted space to avoid partitioning. And if we agree that a file
|
53
|
+
can not be changed after it is uploaded (file immutability) we strongly simplify our lives as now we always have unique
|
54
|
+
correspondence between file ID and its content.
|
55
|
+
|
56
|
+
For example, we can tell Nginx to cache forever any image or its derivative simply by its URL of form
|
57
|
+
`/neofiles/serve-image/ID(/WxH)` since we know that no mater what, the content represented by this URL is always the same.
|
58
|
+
(Well, we can change watermarks — but this happens rarely, and eventually the whole cache will be updated).
|
59
|
+
|
60
|
+
Or on upload we can check if the same file exists in DB (by md5 hash) and if it is, create new file metadata pointing
|
61
|
+
to the same set of file chunks (byte content).
|
62
|
+
|
63
|
+
So, Neofiles does not automatically delete or alter existing files, only their metadata, which is ok.
|
64
|
+
|
65
|
+
***With all this in mind***, Neofiles can be viewed as a remote filesystem, where files with their metadata
|
66
|
+
are addressed and used by their IDs, as in `belongs_to/has_many`, and real file fetching (and postprocessing) is done
|
67
|
+
via HTTP requests to Content Delivery Network represented by a set of streaming controllers + caching frontend webserver
|
68
|
+
setup.
|
69
|
+
|
70
|
+
Installation, dependencies
|
71
|
+
--------------------------
|
72
|
+
|
73
|
+
Add Neofiles and its dependencies to your gemfile:
|
74
|
+
|
75
|
+
``` ruby
|
76
|
+
gem 'neofiles', git: 'git@bitbucket.org:neolabs-kz/gem_neo_files.git'
|
77
|
+
gem 'ruby-imagespec', git: 'git://github.com/dim/ruby-imagespec.git'
|
78
|
+
gem 'mini_magick', '3.7.0'
|
79
|
+
```
|
80
|
+
|
81
|
+
***ruby-imagespec*** is needed to get an image file dimensions & content type.
|
82
|
+
|
83
|
+
***mini_magick*** does resizing & watermarking. Actually it is a lightweight wrapper around command-line utility
|
84
|
+
ImageMagick, which must be installed also. Refer to the gem's description for installation instructions.
|
85
|
+
|
86
|
+
Also, you must have installed MongoDB with its default driver ***mongoid*** (5 version at least) and Rails framework
|
87
|
+
with HAML templating engine. By default the gem needs `neofiles` mongoid client defined in `config/mongoid.yml`, which
|
88
|
+
can be changed in ***Configuration*** section.
|
89
|
+
|
90
|
+
Next, include CSS & JS files where needed (say, application.js or admin.js)...
|
91
|
+
|
92
|
+
``` javascript
|
93
|
+
#= require jquery # neofiles requires jquery
|
94
|
+
#= require neofiles
|
95
|
+
```
|
96
|
+
|
97
|
+
... and application.css/admin.css or whatever place you need it in:
|
98
|
+
|
99
|
+
``` css
|
100
|
+
*= require neofiles
|
101
|
+
```
|
102
|
+
|
103
|
+
The last step is to set up routing which is as simple as adding a line to the `routes.rb`:
|
104
|
+
|
105
|
+
``` ruby
|
106
|
+
instance_eval &Neofiles.routes_proc
|
107
|
+
```
|
108
|
+
|
109
|
+
It produces the following routes:
|
110
|
+
|
111
|
+
```
|
112
|
+
$ rake routes | grep neofiles
|
113
|
+
neofiles_file_compact GET /neofiles/admin/file_compact(.:format) neofiles/admin#file_compact
|
114
|
+
neofiles_file_save POST /neofiles/admin/file_save(.:format) neofiles/admin#file_save
|
115
|
+
neofiles_file_remove POST /neofiles/admin/file_remove(.:format) neofiles/admin#file_remove
|
116
|
+
neofiles_file_update POST /neofiles/admin/file_update(.:format) neofiles/admin#file_update
|
117
|
+
neofiles_redactor_upload POST /neofiles/admin/redactor-upload(.:format) neofiles/admin#redactor_upload
|
118
|
+
neofiles_redactor_list GET /neofiles/admin/redactor-list/:owner_type/:owner_id/:type(.:format) neofiles/admin#redactor_list
|
119
|
+
neofiles_file GET /neofiles/serve/:id(.:format) neofiles/files#show
|
120
|
+
neofiles_image GET /neofiles/serve-image/:id(/:format(/c:crop)(/q:quality)) neofiles/images#show {:format=>/[1-9]\d*x[1-9]\d*/, :crop=>/[10]/, :quality=>/[1-9]\d*/}
|
121
|
+
neofiles_image_nowm GET /neofiles/nowm-serve-image/:id(.:format) neofiles/images#show {:nowm=>true}
|
122
|
+
```
|
123
|
+
|
124
|
+
Routes `/neofiles/admin/*` form AJAX backend for file manipulations. The last 3 routes are for streaming controllers.
|
125
|
+
|
126
|
+
Usage with CCK
|
127
|
+
--------------
|
128
|
+
|
129
|
+
Neofiles gem is used mainly with two other gems: cck & cck_forms (CCK stands for Content Construction Kit).
|
130
|
+
|
131
|
+
Using these gems together provides straightforward and extremely easy way to handle file storage and manipulation.
|
132
|
+
|
133
|
+
***As cck & cck_forms are yet to be published (soon), I will only show the basic usage.***
|
134
|
+
|
135
|
+
``` ruby
|
136
|
+
# in model, say app/models/user.rb
|
137
|
+
class User
|
138
|
+
include Mongoid::Document
|
139
|
+
|
140
|
+
field :avatar, type: Cck::ParameterTypeClass::Image
|
141
|
+
field :slider, type: Cck::ParameterTypeClass::Album
|
142
|
+
end
|
143
|
+
|
144
|
+
# in form view, say app/views/admin/users/edit.haml
|
145
|
+
= form_for @user do |f|
|
146
|
+
.form-group
|
147
|
+
label= Avatar image:
|
148
|
+
= f.standalone_cck_field :avatar
|
149
|
+
|
150
|
+
.form-group
|
151
|
+
%label= Slider photos:
|
152
|
+
= f.standalone_cck_field :slider
|
153
|
+
|
154
|
+
# everywhere else where you want to use avatar or slider photos, say on user profile page app/views/users/show.haml
|
155
|
+
.user-profile
|
156
|
+
.avatar
|
157
|
+
= neofiles_img_tag @user.avatar.value, width=100, height=100, {crop: 1}, {alt: "#{@user.name}'s avatar", class: 'avatar-img'}
|
158
|
+
|
159
|
+
.slider
|
160
|
+
= @user.slider.value.each do |img| # img is Neofiles::Image instance
|
161
|
+
.slider-img
|
162
|
+
= neofiles_img_link img, width=800, height=300
|
163
|
+
```
|
164
|
+
|
165
|
+
Note, that fields `avatar` and `slider` are wrappers around real `Neofiles::Image` values, so you need to unwrap them
|
166
|
+
with call to `.value`.
|
167
|
+
|
168
|
+
Standalone usage
|
169
|
+
----------------
|
170
|
+
|
171
|
+
The whole idea is to handle `Neofiles::File` instances via their IDs, without direct files manipulation.
|
172
|
+
|
173
|
+
In your MongoDB model create field to store file ID:
|
174
|
+
|
175
|
+
``` ruby
|
176
|
+
class User
|
177
|
+
include Mongoid::Document
|
178
|
+
|
179
|
+
belongs_to :avatar, class_name: 'Neofiles::Image'
|
180
|
+
belongs_to :cv, class_name: 'Neofiles::File'
|
181
|
+
|
182
|
+
# OR
|
183
|
+
#
|
184
|
+
# field :avatar_id, type: BSON::ObjectID # or type: String
|
185
|
+
#
|
186
|
+
# def avatar
|
187
|
+
# Neofiles::Image.where(id: avatar_id).first if avatar_id.present?
|
188
|
+
# end
|
189
|
+
#
|
190
|
+
# def avatar=(other)
|
191
|
+
# self.avatar_id = other ? other.id : nil
|
192
|
+
# end
|
193
|
+
end
|
194
|
+
```
|
195
|
+
|
196
|
+
With ActiveRecord, create ID field in database schema and define getter and setter to construct a `Neofiles::File`
|
197
|
+
instance like in example above.
|
198
|
+
|
199
|
+
Next, to build an edit form, construct an AJAX request to special action `Neofiles::AdminController#file_compact`, it
|
200
|
+
will generate HTML subform for file upload/edit. The subform contains all HTML & JS needed to asynchronously upload/edit
|
201
|
+
or delete file. Most importantly it contains so-called ***transfer input*** (hidden field) which gets populated with ID
|
202
|
+
of the newly created `Neofiles::File` instance on file upload (also it is emptied when a file is deleted). The key is this
|
203
|
+
input should have its `name` attribute in context of the outer form (of the host object) — you pass that name as an AJAX
|
204
|
+
parameter. Hence when a user saves the outer form, the ID value will be persisted alongside other host object fields.
|
205
|
+
|
206
|
+
``` haml
|
207
|
+
= form_for @user do |f|
|
208
|
+
.form-group
|
209
|
+
%label= Avatar image
|
210
|
+
#avatar-container
|
211
|
+
= f.hidden_field :avatar_id
|
212
|
+
|
213
|
+
- file_compact_path = neofiles_file_compact_path(id: @user.avatar_id, input_name: 'user[avatar]')
|
214
|
+
:javascript
|
215
|
+
$(function() {
|
216
|
+
$("#avatar-container").load("#{file_compact_path}", null, function() {
|
217
|
+
$(this).children().unwrap();
|
218
|
+
});
|
219
|
+
})
|
220
|
+
```
|
221
|
+
|
222
|
+
The reason for inserting default hidden field is that an AJAX request can take long to load or even fail, and all this
|
223
|
+
time there will be no input with name `user[avatar]`, so controller may be confused and nullify that field if the "Save"
|
224
|
+
button is pressed by an impatient user.
|
225
|
+
|
226
|
+
Now, we can freely use the value stored, either directly of via helper:
|
227
|
+
|
228
|
+
``` haml
|
229
|
+
- pic = @user.avatar
|
230
|
+
- if pic
|
231
|
+
This user has an avatar image of type #{pic.content_type} and of size #{pic.length} bytes.
|
232
|
+
%br
|
233
|
+
The original filename was #{pic.filename}, MD5 hash is #{pic.md5}.
|
234
|
+
%br
|
235
|
+
The image is:
|
236
|
+
%img{src: neofiles_image_url(pic, format: '100x100', crop: '1', q: '90'), width: 100, height: 100}
|
237
|
+
|
238
|
+
/ OR EQUIVALENTLY
|
239
|
+
|
240
|
+
= neofiles_img_tag pic, 100, 100, crop: 1, q: 90
|
241
|
+
```
|
242
|
+
|
243
|
+
Delivering bytes
|
244
|
+
----------------
|
245
|
+
|
246
|
+
To actually get file bytes to users Neofiles offers two controllers — `FilesController` and `ImagesController` — and
|
247
|
+
three routes: `neofiles_file_url`, `neofiles_image_url` and `neofiles_image_nowm_url`.
|
248
|
+
|
249
|
+
The `FilesController` delivers bytes as-is, the `ImagesController` allows resizing & watermarking. `nowm` stands for "no
|
250
|
+
watermark" and is used when an admin is logged in (see ***Watermarking*** section).
|
251
|
+
|
252
|
+
The actual URLs look like this: `/neofiles/serve-file/FILE_ID`, `/neofiles/serve-image/IMAGE_ID/...`,
|
253
|
+
`/neofiles/nowm-serve-image/IMAGE_ID/...` (prefixed with domain and protocol).
|
254
|
+
|
255
|
+
When you request an image, you have several parameters to pass along:
|
256
|
+
|
257
|
+
* `format`: a string of form `WxH`, where `W` and `H` are max width and height correspondingly, that is the returned
|
258
|
+
image will be no greater than that size.
|
259
|
+
* `crop`: a string, if `'1'` is passed, the image will be cropped and the aspect ratio of the resulting image will
|
260
|
+
always be `W/H` (from the `format` parameter). Otherwise (default) the original aspect ratio will be preserved.
|
261
|
+
* `q`: an integer from 1 till 100. If passed, the image will be forced to JPEG format with the specified quality.
|
262
|
+
|
263
|
+
It is ok to request an image via the `FilesController` as it is smart enough to redirect to the correct path.
|
264
|
+
|
265
|
+
***Production notes***:
|
266
|
+
|
267
|
+
1. It may be good to put the burden of serving files to a different server than where your main application resides.
|
268
|
+
Create a new environment called `neofiles` and setup its deploy accordingly (leave only Neofiles and MongoDB related
|
269
|
+
things).
|
270
|
+
|
271
|
+
1. Server from point (1) forms naturally a simple CDN: give it a proper name, say `strg.domain.com`, set it inside
|
272
|
+
your neofiles config as `cdns` and all your files will be downloaded faster since browser can now send more
|
273
|
+
parallel requests.
|
274
|
+
|
275
|
+
If the server is powerful enough create even more domains like `str1/2/3...` pointing to it to get
|
276
|
+
even more speed.
|
277
|
+
|
278
|
+
1. (1) + (2) lead to the rule: always use `*_url` route helpers instead of `*_path` ones, as the former takes into
|
279
|
+
account `cdns`.
|
280
|
+
|
281
|
+
1. Make sure your session cookies (or other means of identifying admins) are available to CDN domains since they need
|
282
|
+
to check for `is_admin?`.
|
283
|
+
|
284
|
+
1. You ***must*** set up caching in front of streaming controllers, with one exception: `/neofiles/nowm-serve-image`
|
285
|
+
must always hit the application as it checks if an admin is logged in. If you cache it you will give everyone
|
286
|
+
watermarkless cached copies of image originals. Example Nginx config:
|
287
|
+
|
288
|
+
server {
|
289
|
+
listen 80;
|
290
|
+
server_name strg1.domain.com strg2.domain.com;
|
291
|
+
root /var/www/neofiles/current/public;
|
292
|
+
|
293
|
+
location /neofiles/serve {
|
294
|
+
|
295
|
+
if ($http_if_modified_since) {
|
296
|
+
return 304;
|
297
|
+
}
|
298
|
+
if ($http_if_none_match) {
|
299
|
+
return 304;
|
300
|
+
}
|
301
|
+
|
302
|
+
expires max;
|
303
|
+
add_header Cache-Control public;
|
304
|
+
add_header Last-Modified "Sat, 1 Jan 2012 00:00:00 GMT";
|
305
|
+
|
306
|
+
proxy_cache_valid 200 30d;
|
307
|
+
proxy_cache_valid 404 301 302 304 5m;
|
308
|
+
proxy_cache_key "$request_uri";
|
309
|
+
proxy_ignore_headers "Expires" "Cache-Control" "Set-Cookie";
|
310
|
+
|
311
|
+
proxy_cache neofiles;
|
312
|
+
proxy_pass http://neofiles;
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
upstream neofiles {
|
317
|
+
server unix:/var/run/neofiles.sock;
|
318
|
+
}
|
319
|
+
|
320
|
+
View helpers
|
321
|
+
------------
|
322
|
+
|
323
|
+
The following view helpers are available, by example:
|
324
|
+
|
325
|
+
``` haml
|
326
|
+
- file = Neofiles::File.first
|
327
|
+
- image = Neofiles::Image.first
|
328
|
+
- swf = Neofiles::Swf.first
|
329
|
+
|
330
|
+
# <img src="/neofiles/serve-image/..." alt="..." width...>
|
331
|
+
= neofiles_img_tag image, 100, 100, {crop: 1}, {alt: '...'}
|
332
|
+
|
333
|
+
# <a href="/neofiles/serve-image/..." title="See fullsize"><img src=....></a>
|
334
|
+
= neofiles_img_link image, 100, 100, {crop: 0, q: 50}, {title: 'See fullsize'}, {alt: '...}
|
335
|
+
|
336
|
+
# <a href="/neofiles/serve-file/..." title="Download it!">My CV</a>
|
337
|
+
= neofiles_link file, "My CV", title: "Download it!"
|
338
|
+
|
339
|
+
# <object id="bnr_object_1" width... classid...>...</object>
|
340
|
+
= swf_embed 'bnr_object_1', neofiles_image_url(swf), swf.width, swf.height, '#f00', ''
|
341
|
+
```
|
342
|
+
|
343
|
+
Watermarks
|
344
|
+
----------
|
345
|
+
|
346
|
+
By default this gem watermarks images with a single watermark (at the bottom) from `app/assets/images/neofiles/watermark.png`
|
347
|
+
(it is a 1x1 transparent pixel by default). You can change this by redefining the config option `config.neofiles.watermarker`.
|
348
|
+
Its value must be a proc with signature `image, no_watermark:, watermark_width:, watermark_height:`. The arguments
|
349
|
+
are:
|
350
|
+
|
351
|
+
* `image`: a `MiniMagick::Image` instance to be watermarked.
|
352
|
+
* `no_watermark`: if this is `true` the proc must return the image's blob intact
|
353
|
+
* `watermark_width`, `watermark_height`: the image dimensions
|
354
|
+
|
355
|
+
The returned value must be converted to blob by the `MiniMagick::Image#to_blob` method.
|
356
|
+
|
357
|
+
As admins usually need watermarkless originals of images, you can specify the current admin via `config.neofiles.current_admin`.
|
358
|
+
If that proc returns something truthy a request to `/neofiles/nowm-serve-image/...` will not stamp watermarks. Otherwise
|
359
|
+
it will return an HTTP 403 Forbidden response. Check out watermarks caching problems in ***Delivering bytes*** section.
|
360
|
+
|
361
|
+
Configuration
|
362
|
+
-------------
|
363
|
+
|
364
|
+
Neofiles offers the following config options which can be set in `config/application.rb` or `config/environments/*.rb`:
|
365
|
+
|
366
|
+
``` ruby
|
367
|
+
# array of CDN strings like 'http://strg1.example.com'
|
368
|
+
config.neofiles.cdns = []
|
369
|
+
|
370
|
+
# if you need some special logic done before file save IN ADMIN CONTROLLER, put it here
|
371
|
+
# `file` is a Neofiles::File instance
|
372
|
+
config.neofiles.before_save = ->(file) do
|
373
|
+
...
|
374
|
+
end
|
375
|
+
|
376
|
+
# if you have a notion of "admin" (whatever it is), put here a logic to get the current "admin" object,
|
377
|
+
# it is used only when deciding if the current user can access watermarkless version of an image
|
378
|
+
# (`context` is a controller instance where the proc is called, so with Devise you can just do `context.current_admin`)
|
379
|
+
config.neofiles.current_admin = ->(context) do
|
380
|
+
...
|
381
|
+
end
|
382
|
+
|
383
|
+
# mongo specific settings — override them if you need to store data in some other database and/or collections
|
384
|
+
config.neofiles.mongo_files_collection = 'files.files'
|
385
|
+
config.neofiles.mongo_chunks_collection = 'files.chunks'
|
386
|
+
config.neofiles.mongo_client = 'neofiles'
|
387
|
+
config.neofiles.mongo_default_chunk_size = 4.megabytes
|
388
|
+
|
389
|
+
# image related settings
|
390
|
+
config.neofiles.image_rotate_exif = true # rotate image, if exif contains orientation info
|
391
|
+
config.neofiles.image_clean_exif = true # clean all exif fields on save
|
392
|
+
config.neofiles.image_max_dimensions = nil # resize huge originals to meaningful size: [w, h], {width: w, height: h}, wh
|
393
|
+
config.neofiles.image_max_crop_width = 2000 # users can request resizing only up to this width
|
394
|
+
config.neofiles.image_max_crop_height = 2000 # users can request resizing only up to this height
|
395
|
+
|
396
|
+
# default watermarker — redefine to set special watermarking logic
|
397
|
+
# by default, watermark only images larger than 300x300 with a watermark at the bottom center, taken from
|
398
|
+
# app/assets/images/neofiles/watermark.png
|
399
|
+
config.neofiles.watermarker = ->(image, no_watermark: false, watermark_width:, watermark_height:) do
|
400
|
+
...
|
401
|
+
end
|
402
|
+
```
|
403
|
+
|
404
|
+
Roadmap, TODOs
|
405
|
+
--------------
|
406
|
+
|
407
|
+
* Move HTML-building methods `admin_compact_view` to views or helper.
|
408
|
+
* Add proper authorization for admin controllers.
|
409
|
+
* Speed up image resize (`Image#save_file` has unnecessary steps).
|
410
|
+
* Move airbrake `notify_airbrake` calls to config.
|
411
|
+
* Configurable WYCIWYG editor (on/off, ability to use other than proprietary RadactorJS).
|
412
|
+
* Transform controller exceptions into meaningful error messages to users.
|
413
|
+
|
414
|
+
License
|
415
|
+
-------
|
416
|
+
|
417
|
+
Released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Cck'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
33
|
+
t.libs << 'lib'
|
34
|
+
t.libs << 'test'
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
36
|
+
t.verbose = false
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|