upload_documents_tool 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at lemiszewski@gmx.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in upload_documents_tool.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,175 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ upload_documents_tool (0.1.0)
5
+ bootstrap-kaminari-views (~> 0.0.5)
6
+ bootstrap-sass
7
+ font-awesome-sass
8
+ jasny-bootstrap-rails
9
+ jquery-rails
10
+ kaminari (~> 1.0.1)
11
+ railties (~> 4.2.6)
12
+ toastr-rails
13
+
14
+ GEM
15
+ remote: https://rubygems.org/
16
+ specs:
17
+ actionmailer (4.2.10)
18
+ actionpack (= 4.2.10)
19
+ actionview (= 4.2.10)
20
+ activejob (= 4.2.10)
21
+ mail (~> 2.5, >= 2.5.4)
22
+ rails-dom-testing (~> 1.0, >= 1.0.5)
23
+ actionpack (4.2.10)
24
+ actionview (= 4.2.10)
25
+ activesupport (= 4.2.10)
26
+ rack (~> 1.6)
27
+ rack-test (~> 0.6.2)
28
+ rails-dom-testing (~> 1.0, >= 1.0.5)
29
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
30
+ actionview (4.2.10)
31
+ activesupport (= 4.2.10)
32
+ builder (~> 3.1)
33
+ erubis (~> 2.7.0)
34
+ rails-dom-testing (~> 1.0, >= 1.0.5)
35
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
36
+ activejob (4.2.10)
37
+ activesupport (= 4.2.10)
38
+ globalid (>= 0.3.0)
39
+ activemodel (4.2.10)
40
+ activesupport (= 4.2.10)
41
+ builder (~> 3.1)
42
+ activerecord (4.2.10)
43
+ activemodel (= 4.2.10)
44
+ activesupport (= 4.2.10)
45
+ arel (~> 6.0)
46
+ activesupport (4.2.10)
47
+ i18n (~> 0.7)
48
+ minitest (~> 5.1)
49
+ thread_safe (~> 0.3, >= 0.3.4)
50
+ tzinfo (~> 1.1)
51
+ arel (6.0.4)
52
+ autoprefixer-rails (7.1.4.1)
53
+ execjs
54
+ bootstrap-kaminari-views (0.0.5)
55
+ kaminari (>= 0.13)
56
+ rails (>= 3.1)
57
+ bootstrap-sass (3.3.7)
58
+ autoprefixer-rails (>= 5.2.1)
59
+ sass (>= 3.3.4)
60
+ builder (3.2.3)
61
+ concurrent-ruby (1.0.5)
62
+ crass (1.0.2)
63
+ diff-lcs (1.3)
64
+ erubis (2.7.0)
65
+ execjs (2.7.0)
66
+ ffi (1.9.18)
67
+ font-awesome-sass (4.7.0)
68
+ sass (>= 3.2)
69
+ globalid (0.4.0)
70
+ activesupport (>= 4.2.0)
71
+ i18n (0.8.6)
72
+ jasny-bootstrap-rails (3.1.3)
73
+ railties (>= 3.0)
74
+ jquery-rails (4.3.1)
75
+ rails-dom-testing (>= 1, < 3)
76
+ railties (>= 4.2.0)
77
+ thor (>= 0.14, < 2.0)
78
+ kaminari (1.0.1)
79
+ activesupport (>= 4.1.0)
80
+ kaminari-actionview (= 1.0.1)
81
+ kaminari-activerecord (= 1.0.1)
82
+ kaminari-core (= 1.0.1)
83
+ kaminari-actionview (1.0.1)
84
+ actionview
85
+ kaminari-core (= 1.0.1)
86
+ kaminari-activerecord (1.0.1)
87
+ activerecord
88
+ kaminari-core (= 1.0.1)
89
+ kaminari-core (1.0.1)
90
+ loofah (2.1.1)
91
+ crass (~> 1.0.2)
92
+ nokogiri (>= 1.5.9)
93
+ mail (2.6.6)
94
+ mime-types (>= 1.16, < 4)
95
+ mime-types (3.1)
96
+ mime-types-data (~> 3.2015)
97
+ mime-types-data (3.2016.0521)
98
+ mini_portile2 (2.3.0)
99
+ minitest (5.10.3)
100
+ nokogiri (1.8.1)
101
+ mini_portile2 (~> 2.3.0)
102
+ rack (1.6.8)
103
+ rack-test (0.6.3)
104
+ rack (>= 1.0)
105
+ rails (4.2.10)
106
+ actionmailer (= 4.2.10)
107
+ actionpack (= 4.2.10)
108
+ actionview (= 4.2.10)
109
+ activejob (= 4.2.10)
110
+ activemodel (= 4.2.10)
111
+ activerecord (= 4.2.10)
112
+ activesupport (= 4.2.10)
113
+ bundler (>= 1.3.0, < 2.0)
114
+ railties (= 4.2.10)
115
+ sprockets-rails
116
+ rails-deprecated_sanitizer (1.0.3)
117
+ activesupport (>= 4.2.0.alpha)
118
+ rails-dom-testing (1.0.8)
119
+ activesupport (>= 4.2.0.beta, < 5.0)
120
+ nokogiri (~> 1.6)
121
+ rails-deprecated_sanitizer (>= 1.0.1)
122
+ rails-html-sanitizer (1.0.3)
123
+ loofah (~> 2.0)
124
+ railties (4.2.10)
125
+ actionpack (= 4.2.10)
126
+ activesupport (= 4.2.10)
127
+ rake (>= 0.8.7)
128
+ thor (>= 0.18.1, < 2.0)
129
+ rake (10.5.0)
130
+ rb-fsevent (0.10.2)
131
+ rb-inotify (0.9.10)
132
+ ffi (>= 0.5.0, < 2)
133
+ rspec (3.6.0)
134
+ rspec-core (~> 3.6.0)
135
+ rspec-expectations (~> 3.6.0)
136
+ rspec-mocks (~> 3.6.0)
137
+ rspec-core (3.6.0)
138
+ rspec-support (~> 3.6.0)
139
+ rspec-expectations (3.6.0)
140
+ diff-lcs (>= 1.2.0, < 2.0)
141
+ rspec-support (~> 3.6.0)
142
+ rspec-mocks (3.6.0)
143
+ diff-lcs (>= 1.2.0, < 2.0)
144
+ rspec-support (~> 3.6.0)
145
+ rspec-support (3.6.0)
146
+ sass (3.5.1)
147
+ sass-listen (~> 4.0.0)
148
+ sass-listen (4.0.0)
149
+ rb-fsevent (~> 0.9, >= 0.9.4)
150
+ rb-inotify (~> 0.9, >= 0.9.7)
151
+ sprockets (3.7.1)
152
+ concurrent-ruby (~> 1.0)
153
+ rack (> 1, < 3)
154
+ sprockets-rails (3.2.1)
155
+ actionpack (>= 4.0)
156
+ activesupport (>= 4.0)
157
+ sprockets (>= 3.0.0)
158
+ thor (0.20.0)
159
+ thread_safe (0.3.6)
160
+ toastr-rails (1.0.3)
161
+ railties (>= 3.1.0)
162
+ tzinfo (1.2.3)
163
+ thread_safe (~> 0.1)
164
+
165
+ PLATFORMS
166
+ ruby
167
+
168
+ DEPENDENCIES
169
+ bundler (~> 1.16.a)
170
+ rake (~> 10.0)
171
+ rspec (~> 3.0)
172
+ upload_documents_tool!
173
+
174
+ BUNDLED WITH
175
+ 1.16.0.pre.2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Jakub41
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # UploadDocumentsTool
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/upload_documents_tool`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'upload_documents_tool'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install upload_documents_tool
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/upload_documents_tool. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+
41
+ ## Code of Conduct
42
+
43
+ Everyone interacting in the UploadDocumentsTool project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/upload_documents_tool/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,33 @@
1
+ $ ->
2
+ $.rails.allowAction = (link) ->
3
+ return true unless link.attr('data-confirm')
4
+ $.rails.showConfirmDialog(link)
5
+ false
6
+
7
+ $.rails.confirmed = (link) ->
8
+ link.removeAttr('data-confirm')
9
+ link.trigger('click.rails')
10
+
11
+ $.rails.showConfirmDialog = (link) ->
12
+ message = link.attr 'data-confirm'
13
+ html = """
14
+ <div class="modal" id="confirmationDialog">
15
+ <div class="modal-dialog">
16
+ <div class="modal-content">
17
+ <div class="modal-header">
18
+ <a class="close" data-dismiss="modal">×</a>
19
+ <h1>#{message}</h1>
20
+ </div>
21
+ <div class="modal-body">
22
+ <p>You are about to delete. Do you want to proceed?</p>
23
+ </div>
24
+ <div class="modal-footer">
25
+ <a data-dismiss="modal" class="btn">No</a>
26
+ <a data-dismiss="modal" class="btn btn-danger confirm">Yes</a>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ """
32
+ $(html).modal()
33
+ $('#confirmationDialog .confirm').on 'click', -> $.rails.confirmed(link)
@@ -0,0 +1,39 @@
1
+ function progress_handling(e){
2
+ if(e.lengthComputable){
3
+ var prog = Math.round(e.loaded / e.total * 100);
4
+ $('.progress-bar').css('width',prog.toString()+'%');
5
+ $('#file_progress').html(prog.toString()+'%');
6
+ }
7
+ }
8
+
9
+ function init_upload() {
10
+ $('#new_document').on('submit', function (e) {
11
+ e.preventDefault();
12
+ formData = jQuery(this);
13
+ var fileInput = document.getElementById('document_file');
14
+ var file = fileInput.files[0];
15
+ data = new FormData();
16
+ data.append('authenticity_token', $('#authenticity_token').val())
17
+ data.append('document[file]',file);
18
+ $.ajax({
19
+ url: formData.attr('action'),
20
+ type: formData.attr('method'),
21
+ processData: false,
22
+ contentType: false,
23
+ xhr: function() {
24
+ $('#file_progress_bar').show();
25
+ $('#file_progress_bar').removeClass('hidden');
26
+ var myXhr = $.ajaxSettings.xhr();
27
+ if(myXhr.upload){
28
+ myXhr.upload.addEventListener('progress',progress_handling, false);
29
+ }
30
+ return myXhr;
31
+ },
32
+ data: data
33
+ });
34
+ });
35
+ }
36
+
37
+ $(document).ready(function () {
38
+ init_upload();
39
+ });
@@ -0,0 +1,2 @@
1
+ //= require progress_bar
2
+ //= require documents
File without changes
@@ -0,0 +1,16 @@
1
+ module UploadDocumentToolHelper
2
+ def sortable(column, title = nil)
3
+ title ||= column.titleize
4
+ css_class = column == sort_column ? "current #{sort_direction}" : nil
5
+ direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
6
+ link_to title, { sort: column, direction: direction }, class: css_class
7
+ end
8
+
9
+ def documents_table(documents)
10
+ render 'upload_document_tool/documents', documents: documents
11
+ end
12
+
13
+ def document_form(document)
14
+ render 'upload_document_tool/form', document: document
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ <table class="table table-striped table-hover">
2
+ <div class="pull-left">
3
+ <%= form_tag controller_name, method: :get, id: 'limit_form' do %>
4
+ <div class="select-tag">
5
+ Show <%= select_tag :limit, options_for_select([5, 10, 15, 20], selected: params[:limit] || 10), onchange: "$('#limit_form').submit();" %> documents per page
6
+ </div>
7
+ <% end %>
8
+ </div>
9
+ <thead>
10
+ <tr>
11
+ <th>#</th>
12
+ <th><%= sortable "filename", "File Name"%></th>
13
+ <th><%= sortable "content_type", "Extension"%></th>
14
+ <th><%= sortable "created_at", "Date"%></th>
15
+ <th>Download</th>
16
+ <th>Delete</th>
17
+ </tr>
18
+ </thead>
19
+ <tbody>
20
+ <% documents.each_with_index do |document, idx| %>
21
+ <tr>
22
+ <th scope="row"><%= idx + 1 %></th>
23
+ <td><%= link_to document.filename, document, method: :get %></td>
24
+ <td><%= document.content_type %></td>
25
+ <th><%= document.created_at.strftime('%Y/%m/%d %H:%M') %></th>
26
+ <th><%= link_to document, method: :get, class: 'btn btn-primary' do %><i class="fa fa-download"></i><% end %></th>
27
+ <th><%= link_to document, method: :delete, class: 'btn btn-danger', data: { confirm: 'Are you sure?' } do %>
28
+ <i class="fa fa-trash-o" aria-hidden="true"></i>
29
+ <% end %></th>
30
+ </tr>
31
+ <% end %>
32
+ </tbody>
33
+ </table>
34
+ <div class="row">
35
+ <div class="col-md-6">
36
+ <div class="">
37
+ <%= paginate documents, theme: 'twitter-bootstrap-3' %>
38
+ </div>
39
+ </div>
40
+ </div>
@@ -0,0 +1,21 @@
1
+ <%= form_for(document, html: {class: "form", multipart: true}, remote: true) do |f| %>
2
+ <%= hidden_field_tag :authenticity_token, form_authenticity_token %>
3
+ <%= render "upload_document_tool/form_error", resource: document %>
4
+ <div class="fileinput fileinput-new" data-provides="fileinput">
5
+ <span class="btn btn-default btn-file">
6
+ <span class="fileinput-new">Select file</span>
7
+ <span class="fileinput-exists">Change</span>
8
+ <%= f.file_field :file, required: true %>
9
+ </span>
10
+ <%= f.submit "Upload", class: "btn btn-success" %>
11
+ <span class="fileinput-filename"></span>
12
+ <a href="#" class="close fileinput-exists" data-dismiss="fileinput" style="float: none">&times;</a>
13
+ </div>
14
+ <div class="form-group">
15
+ <small id="file_help" class="form-text text-muted">Upload your file.</small>
16
+ <div id="file_progress_bar" class="progress hidden">
17
+ <div id="file_progress" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <% unless resource.errors.empty? %>
2
+ <script>
3
+ <% resource.errors.each do |k, msg| %>
4
+ toastr['error']('<%= msg %>');
5
+ <% end %>
6
+ </script>
7
+ <% end %>
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "upload_documents_tool"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,86 @@
1
+ module UploadDocumentTool
2
+ class AttachmentContentTypeValidator < ActiveModel::EachValidator
3
+ def initialize(options)
4
+ options[:allow_nil] = true unless options.has_key?(:allow_nil)
5
+ super
6
+ end
7
+
8
+ def self.helper_method_name
9
+ :validates_attachment_content_type
10
+ end
11
+
12
+ def validate_each(record, attribute, value)
13
+ base_attribute = attribute.to_sym
14
+ attribute = "#{attribute}_content_type".to_sym
15
+ value = record.send :read_attribute_for_validation, attribute
16
+
17
+ return if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
18
+
19
+ validate_whitelist(record, attribute, value)
20
+ validate_blacklist(record, attribute, value)
21
+
22
+ if record.errors.include? attribute
23
+ record.errors[attribute].each do |error|
24
+ record.errors.add base_attribute, error
25
+ end
26
+ end
27
+ end
28
+
29
+ def validate_whitelist(record, attribute, value)
30
+ if allowed_types.present? && allowed_types.none? { |type| type === value }
31
+ mark_invalid record, attribute, allowed_types
32
+ end
33
+ end
34
+
35
+ def validate_blacklist(record, attribute, value)
36
+ if forbidden_types.present? && forbidden_types.any? { |type| type === value }
37
+ mark_invalid record, attribute, forbidden_types
38
+ end
39
+ end
40
+
41
+ def mark_invalid(record, attribute, types)
42
+ record.errors.add attribute, :invalid, options.merge(:types => types.join(', '))
43
+ end
44
+
45
+ def allowed_types
46
+ [options[:content_type]].flatten.compact
47
+ end
48
+
49
+ def forbidden_types
50
+ [options[:not]].flatten.compact
51
+ end
52
+
53
+ def check_validity!
54
+ unless options.has_key?(:content_type) || options.has_key?(:not)
55
+ raise ArgumentError, "You must pass in either :content_type or :not to the validator"
56
+ end
57
+ end
58
+ end
59
+
60
+ module HelperMethods
61
+ # Places ActiveModel validations on the content type of the file
62
+ # assigned. The possible options are:
63
+ # * +content_type+: Allowed content types. Can be a single content type
64
+ # or an array. Each type can be a String or a Regexp. It should be
65
+ # noted that Internet Explorer uploads files with content_types that you
66
+ # may not expect. For example, JPEG images are given image/pjpeg and
67
+ # PNGs are image/x-png, so keep that in mind when determining how you
68
+ # match. Allows all by default.
69
+ # * +not+: Forbidden content types.
70
+ # * +message+: The message to display when the uploaded file has an invalid
71
+ # content type.
72
+ # * +if+: A lambda or name of an instance method. Validation will only
73
+ # be run is this lambda or method returns true.
74
+ # * +unless+: Same as +if+ but validates if lambda or method returns false.
75
+ # NOTE: If you do not specify an [attachment]_content_type field on your
76
+ # model, content_type validation will work _ONLY upon assignment_ and
77
+ # re-validation after the instance has been reloaded will always succeed.
78
+ # You'll still need to have a virtual attribute (created by +attr_accessor+)
79
+ # name +[attachment]_content_type+ to be able to use this validator.
80
+ def validates_attachment_content_type(*attr_names)
81
+ options = _merge_attributes(attr_names)
82
+ validates_with AttachmentContentTypeValidator, options.dup
83
+ validate_before_processing AttachmentContentTypeValidator, options.dup
84
+ end
85
+ end
86
+ end