importable_attachments 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +38 -0
- data/MIT-LICENSE +20 -0
- data/README.md +8 -0
- data/README.rdoc +3 -0
- data/Rakefile +29 -0
- data/app/assets/images/importable_attachments/.gitkeep +0 -0
- data/app/assets/images/importable_attachments/buttons/.htaccess +5 -0
- data/app/assets/images/importable_attachments/buttons/download_32.png +0 -0
- data/app/assets/images/importable_attachments/buttons/upload_32.png +0 -0
- data/app/assets/javascripts/importable_attachments/application.js +14 -0
- data/app/assets/javascripts/importable_attachments/attachments.coffee +41 -0
- data/app/assets/stylesheets/importable_attachments/application.css +14 -0
- data/app/assets/stylesheets/importable_attachments/attachments.css +4 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/importable_attachments/application_controller.rb +4 -0
- data/app/controllers/importable_attachments/attachments_controller.rb +190 -0
- data/app/controllers/importable_attachments/versions_controller.rb +87 -0
- data/app/helpers/importable_attachments/application_helper.rb +4 -0
- data/app/models/attachment.rb +24 -0
- data/app/models/importable_attachments/attachment.rb +143 -0
- data/app/models/importable_attachments/version.rb +50 -0
- data/app/validators/existing_class_validator.rb +17 -0
- data/app/validators/importable_attachments/csv_validator.rb +36 -0
- data/app/validators/importable_attachments/excel.rb +18 -0
- data/app/validators/importable_attachments/excel_validator.rb +18 -0
- data/app/views/importable_attachments/attachments/_attachment.html.haml +9 -0
- data/app/views/importable_attachments/attachments/_form.html.haml +22 -0
- data/app/views/importable_attachments/attachments/_nested_form.html.haml +20 -0
- data/app/views/importable_attachments/attachments/edit.html.haml +39 -0
- data/app/views/importable_attachments/attachments/index.html.haml +23 -0
- data/app/views/importable_attachments/attachments/index.xml.builder +23 -0
- data/app/views/importable_attachments/attachments/new.html.haml +10 -0
- data/app/views/importable_attachments/attachments/show.html.haml +43 -0
- data/app/views/importable_attachments/versions/_form.html.haml +25 -0
- data/app/views/importable_attachments/versions/edit.html.haml +7 -0
- data/app/views/importable_attachments/versions/index.html.haml +27 -0
- data/app/views/importable_attachments/versions/new.html.haml +5 -0
- data/app/views/importable_attachments/versions/show.html.haml +21 -0
- data/app/views/layouts/_version.html.haml +33 -0
- data/app/views/layouts/importable_attachments/application.html.haml +48 -0
- data/bin/set_lc.sh +47 -0
- data/config/database.yml +25 -0
- data/config/features/attachments.rb +8 -0
- data/config/features/mark_requirements.rb +3 -0
- data/config/features/smarter_dates.rb +3 -0
- data/config/features/versioning.rb +7 -0
- data/config/initializers/0_configuration.rb +7 -0
- data/config/initializers/formtastic.rb +76 -0
- data/config/initializers/generators.rb +10 -0
- data/config/initializers/paperclip.rb +27 -0
- data/config/locales/responders.en.yml +10 -0
- data/config/routes.rb +11 -0
- data/db/migrate/001_create_importable_attachments_versions.rb +14 -0
- data/db/migrate/100_create_attachments.rb +19 -0
- data/importable_attachments.gemspec +81 -0
- data/lib/generators/importable_attachments/install_generator.rb +66 -0
- data/lib/generators/importable_attachments/templates/features/attachments.rb.erb +7 -0
- data/lib/generators/importable_attachments/templates/features/versioning.rb +7 -0
- data/lib/generators/importable_attachments/templates/initializers/paperclip.rb +27 -0
- data/lib/importable_attachments/base.rb +108 -0
- data/lib/importable_attachments/blueprints.rb +9 -0
- data/lib/importable_attachments/engine.rb +8 -0
- data/lib/importable_attachments/importers/csv.rb +208 -0
- data/lib/importable_attachments/importers/excel.rb +37 -0
- data/lib/importable_attachments/importers.rb +7 -0
- data/lib/importable_attachments/version.rb +3 -0
- data/lib/importable_attachments.rb +9 -0
- data/lib/paperclip_processors/save_upload.rb +33 -0
- data/lib/tasks/importable_attachments_tasks.rake +4 -0
- data/script/rails +8 -0
- data/spec/attachments/books.csv +6 -0
- data/spec/attachments/books.txt +6 -0
- data/spec/attachments/books2.csv +4 -0
- data/spec/attachments/empty.csv +0 -0
- data/spec/attachments/failed_instances.csv +3 -0
- data/spec/attachments/invalid_headers.csv +3 -0
- data/spec/attachments/just_headers.csv +1 -0
- data/spec/attachments/mostly_empty.csv +2 -0
- data/spec/attachments/mostly_empty_copy.xls +0 -0
- data/spec/controllers/importable_attachments/attachments_controller_spec.rb +236 -0
- data/spec/controllers/importable_attachments/versions_controller_spec.rb +158 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/book.rb +13 -0
- data/spec/dummy/app/models/library.rb +54 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +65 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/0_configuration.rb +7 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/101_create_libraries.rb +10 -0
- data/spec/dummy/db/migrate/102_create_books.rb +12 -0
- data/spec/dummy/db/schema.rb +57 -0
- data/spec/dummy/features/person_uploads_generic_file.feature +11 -0
- data/spec/dummy/features/step_definitions/person_uploads_generic_file_steps.rb +11 -0
- data/spec/dummy/features/step_definitions/web_steps.rb +211 -0
- data/spec/dummy/features/support/capybara.rb +6 -0
- data/spec/dummy/features/support/database_cleaner.rb +26 -0
- data/spec/dummy/features/support/developer_helpers.rb +47 -0
- data/spec/dummy/features/support/env.rb +53 -0
- data/spec/dummy/features/support/paths.rb +33 -0
- data/spec/dummy/features/support/poltergeist.rb +1 -0
- data/spec/dummy/features/support/selectors.rb +39 -0
- data/spec/dummy/features/support/transactional_fixtures.rb +14 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +38 -0
- data/spec/dummy/public/422.html +38 -0
- data/spec/dummy/public/500.html +36 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/support/.gitkeep +0 -0
- data/spec/dummy/spec/support/paperclip.rb +1 -0
- data/spec/models/importable_attachments/attachment_spec.rb +177 -0
- data/spec/models/importable_attachments/library_spec.rb +155 -0
- data/spec/models/importable_attachments/version_spec.rb +25 -0
- data/spec/routing/importable_attachments/versions_routing_spec.rb +43 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +30 -0
- metadata +737 -0
data/bin/set_lc.sh
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Pick one EVENT or SWIFTIPLY
|
2
|
+
# To run a Rails app in evented mode (eventmachine gem)
|
3
|
+
export EVENT=1
|
4
|
+
|
5
|
+
# To run in swiftiplied mode (swiftiply gem)
|
6
|
+
#export SWIFTIPLY=1
|
7
|
+
|
8
|
+
# HACK: broken locales
|
9
|
+
my_hosttype="${HOSTTYPE:='unknown_hosttype'}"
|
10
|
+
my_kernel="${OSTYPE:='unknown_kernel'}"
|
11
|
+
my_hosttype=$(uname -a)
|
12
|
+
my_kernel=$(uname -s)
|
13
|
+
|
14
|
+
if [ "${my_kernel}" != 'Darwin' ]; then
|
15
|
+
my_kernel="${my_kernel/SunOS/solaris}"
|
16
|
+
fi
|
17
|
+
|
18
|
+
# TODO: re-write my_osver detection to include major-minor-patch
|
19
|
+
my_ostype="${my_kernel/Darwin*/darwin}"
|
20
|
+
my_osver="${my_kernel/darwin/}"
|
21
|
+
|
22
|
+
if [ "${my_ostype}" != 'darwin' ]; then
|
23
|
+
my_ostype="${my_kernel/Linux*/linux}"
|
24
|
+
if [ "${my_ostype}" != 'linux' ]; then
|
25
|
+
my_ostype="${my_kernel/-gnu/}"
|
26
|
+
fi
|
27
|
+
my_osver="${my_kernel/linux-/}"
|
28
|
+
if [ ${my_ostype} != 'linux' ]; then
|
29
|
+
my_ostype="${my_kernel/solaris*/solaris}"
|
30
|
+
my_osver="${my_kernel/solaris/}"
|
31
|
+
fi
|
32
|
+
fi
|
33
|
+
|
34
|
+
case "${my_ostype}" in
|
35
|
+
'darwin' )
|
36
|
+
LC_CTYPE='en_US.UTF-8'; builtin export LC_CTYPE
|
37
|
+
LC_ALL='en_US.UTF-8'; builtin export LC_ALL # Mnt. Lion
|
38
|
+
;;
|
39
|
+
'linux' )
|
40
|
+
LANG='en_US.UTF-8'; builtin export LANG
|
41
|
+
LC_ALL='en_US.UTF-8'; builtin export LC_ALL
|
42
|
+
;;
|
43
|
+
* )
|
44
|
+
echo "Unsupported OS: ${my_ostype}"
|
45
|
+
;;
|
46
|
+
esac
|
47
|
+
|
data/config/database.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# SQLite version 3.x
|
2
|
+
# gem install sqlite3
|
3
|
+
#
|
4
|
+
# Ensure the SQLite 3 gem is defined in your Gemfile
|
5
|
+
# gem 'sqlite3'
|
6
|
+
development:
|
7
|
+
adapter: sqlite3
|
8
|
+
database: db/development.sqlite3
|
9
|
+
pool: 5
|
10
|
+
timeout: 5000
|
11
|
+
|
12
|
+
# Warning: The database defined as "test" will be erased and
|
13
|
+
# re-generated from your development database when you run "rake".
|
14
|
+
# Do not set this db to the same as development or production.
|
15
|
+
test:
|
16
|
+
adapter: sqlite3
|
17
|
+
database: ":memory:"
|
18
|
+
pool: 5
|
19
|
+
timeout: 5000
|
20
|
+
|
21
|
+
production:
|
22
|
+
adapter: sqlite3
|
23
|
+
database: db/production.sqlite3
|
24
|
+
pool: 5
|
25
|
+
timeout: 5000
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Configuration.for('attachments') do
|
2
|
+
enabled true
|
3
|
+
include_revision_in_filename false
|
4
|
+
validate_on_import true
|
5
|
+
path ':rails_root/public/system/:rails_env/:style/:attachable_klass/:id_partition/:basename.:extension'
|
6
|
+
url %w(development test).include?(Rails.env) ? '/attachments/:id/download' : '/system/:rails_env/:style/:attachable_klass/:id_partition/:basename.:extension'
|
7
|
+
end
|
8
|
+
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Configuration.for('versioning') do
|
2
|
+
enabled true
|
3
|
+
validate_item_type_constants true
|
4
|
+
path ':rails_root/public/system/:rails_env/:style/:attachable_klass/:id_partition/:basename.:stream_version.:extension'
|
5
|
+
url %w(development test).include?(Rails.env) ? '/attachments/:id/download' : '/system/:rails_env/:style/:attachable_klass/:id_partition/:basename.:stream_version.:extension'
|
6
|
+
end
|
7
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Set the default text field size when input is a string. Default is nil.
|
4
|
+
# Formtastic::FormBuilder.default_text_field_size = 50
|
5
|
+
|
6
|
+
# Set the default text area height when input is a text. Default is 20.
|
7
|
+
# Formtastic::FormBuilder.default_text_area_height = 5
|
8
|
+
|
9
|
+
# Set the default text area width when input is a text. Default is nil.
|
10
|
+
# Formtastic::FormBuilder.default_text_area_width = 50
|
11
|
+
|
12
|
+
# Should all fields be considered "required" by default?
|
13
|
+
# Defaults to true.
|
14
|
+
# Formtastic::FormBuilder.all_fields_required_by_default = true
|
15
|
+
|
16
|
+
# Should select fields have a blank option/prompt by default?
|
17
|
+
# Defaults to true.
|
18
|
+
# Formtastic::FormBuilder.include_blank_for_select_by_default = true
|
19
|
+
|
20
|
+
# Set the string that will be appended to the labels/fieldsets which are required
|
21
|
+
# It accepts string or procs and the default is a localized version of
|
22
|
+
# '<abbr title="required">*</abbr>'. In other words, if you configure formtastic.required
|
23
|
+
# in your locale, it will replace the abbr title properly. But if you don't want to use
|
24
|
+
# abbr tag, you can simply give a string as below
|
25
|
+
# Formtastic::FormBuilder.required_string = "(required)"
|
26
|
+
|
27
|
+
# Set the string that will be appended to the labels/fieldsets which are optional
|
28
|
+
# Defaults to an empty string ("") and also accepts procs (see required_string above)
|
29
|
+
# Formtastic::FormBuilder.optional_string = "(optional)"
|
30
|
+
|
31
|
+
# Set the way inline errors will be displayed.
|
32
|
+
# Defaults to :sentence, valid options are :sentence, :list, :first and :none
|
33
|
+
# Formtastic::FormBuilder.inline_errors = :sentence
|
34
|
+
# Formtastic uses the following classes as default for hints, inline_errors and error list
|
35
|
+
|
36
|
+
# If you override the class here, please ensure to override it in your stylesheets as well
|
37
|
+
# Formtastic::FormBuilder.default_hint_class = "inline-hints"
|
38
|
+
# Formtastic::FormBuilder.default_inline_error_class = "inline-errors"
|
39
|
+
# Formtastic::FormBuilder.default_error_list_class = "errors"
|
40
|
+
|
41
|
+
# Set the method to call on label text to transform or format it for human-friendly
|
42
|
+
# reading when formtastic is used without object. Defaults to :humanize.
|
43
|
+
# Formtastic::FormBuilder.label_str_method = :humanize
|
44
|
+
|
45
|
+
# Set the array of methods to try calling on parent objects in :select and :radio inputs
|
46
|
+
# for the text inside each @<option>@ tag or alongside each radio @<input>@. The first method
|
47
|
+
# that is found on the object will be used.
|
48
|
+
# Defaults to ["to_label", "display_name", "full_name", "name", "title", "username", "login", "value", "to_s"]
|
49
|
+
# Formtastic::FormBuilder.collection_label_methods = [
|
50
|
+
# "to_label", "display_name", "full_name", "name", "title", "username", "login", "value", "to_s"]
|
51
|
+
|
52
|
+
# Specifies if labels/hints for input fields automatically be looked up using I18n.
|
53
|
+
# Default value: true. Overridden for specific fields by setting value to true,
|
54
|
+
# i.e. :label => true, or :hint => true (or opposite depending on initialized value)
|
55
|
+
# Formtastic::FormBuilder.i18n_lookups_by_default = false
|
56
|
+
|
57
|
+
# Specifies if I18n lookups of the default I18n Localizer should be cached to improve performance.
|
58
|
+
# Defaults to true.
|
59
|
+
# Formtastic::FormBuilder.i18n_cache_lookups = false
|
60
|
+
|
61
|
+
# Specifies the class to use for localization lookups. You can create your own
|
62
|
+
# class and use it instead by subclassing Formtastic::Localizer (which is the default).
|
63
|
+
# Formtastic::FormBuilder.i18n_localizer = MyOwnLocalizer
|
64
|
+
|
65
|
+
# You can add custom inputs or override parts of Formtastic by subclassing Formtastic::FormBuilder and
|
66
|
+
# specifying that class here. Defaults to Formtastic::FormBuilder.
|
67
|
+
# Formtastic::Helpers::FormHelper.builder = MyCustomBuilder
|
68
|
+
|
69
|
+
# You can opt-in to Formtastic's use of the HTML5 `required` attribute on `<input>`, `<select>`
|
70
|
+
# and `<textarea>` tags by setting this to false (defaults to true).
|
71
|
+
# Formtastic::FormBuilder.use_required_attribute = true
|
72
|
+
|
73
|
+
# You can opt-in to new HTML5 browser validations (for things like email and url inputs) by setting
|
74
|
+
# this to false. Doing so will add a `novalidate` attribute to the `<form>` tag.
|
75
|
+
# See http://diveintohtml5.org/forms.html#validation for more info.
|
76
|
+
# Formtastic::FormBuilder.perform_browser_validations = true
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Paperclip.interpolates :stream_version do |attachment, _|
|
2
|
+
attachment.instance.revision_number
|
3
|
+
end
|
4
|
+
|
5
|
+
Paperclip.interpolates :attachable_klass do |attachment, _|
|
6
|
+
attachable_type = attachment.instance.attachable_type
|
7
|
+
attachable_type && attachable_type.respond_to?(:tableize) ? attachable_type.tableize : '.'
|
8
|
+
end
|
9
|
+
|
10
|
+
Paperclip.interpolates :rails_env do |_, _|
|
11
|
+
Rails.env
|
12
|
+
end
|
13
|
+
|
14
|
+
# brew on darwin
|
15
|
+
if File.directory?(File.join("", 'usr', 'local', 'bin'))
|
16
|
+
Paperclip.options[:command_path] = '/usr/local/bin'
|
17
|
+
|
18
|
+
# macports on darwin
|
19
|
+
elsif File.directory?(File.join("", 'opt', 'local', 'bin'))
|
20
|
+
Paperclip.options[:command_path] = '/opt/local/bin'
|
21
|
+
|
22
|
+
# "disabled" macports due to brew on darwin
|
23
|
+
elsif File.directory?(File.join("", 'opt', 'local.brew', 'bin'))
|
24
|
+
Paperclip.options[:command_path] = '/opt/local.brew/bin'
|
25
|
+
else
|
26
|
+
raise RuntimeError, 'can not locate identify binary'
|
27
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
en:
|
2
|
+
flash:
|
3
|
+
actions:
|
4
|
+
create:
|
5
|
+
notice: '%{resource_name} was successfully created.'
|
6
|
+
update:
|
7
|
+
notice: '%{resource_name} was successfully updated.'
|
8
|
+
destroy:
|
9
|
+
notice: '%{resource_name} was successfully destroyed.'
|
10
|
+
alert: '%{resource_name} could not be destroyed.'
|
data/config/routes.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
ImportableAttachments::Engine.routes.draw do
|
2
|
+
root to: 'attachments#index'
|
3
|
+
resources :versions
|
4
|
+
resources :attachments
|
5
|
+
match 'attachments/:id/download', action: :download, via: :get
|
6
|
+
end
|
7
|
+
|
8
|
+
Rails.application.routes.draw do
|
9
|
+
resources :attachments, controller: 'importable_attachments/attachments'
|
10
|
+
match 'attachments/:id/download', controller: 'importable_attachments/attachments', action: :download, via: :get
|
11
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateImportableAttachmentsVersions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :importable_attachments_versions, force: true do |t|
|
4
|
+
t.string :item_type, null: false
|
5
|
+
t.string :item_id, null: false # item_type.id generally should be GUID
|
6
|
+
t.string :event, null: false
|
7
|
+
t.string :whodunnit
|
8
|
+
t.text :object
|
9
|
+
t.datetime :created_at
|
10
|
+
end
|
11
|
+
add_index :importable_attachments_versions, [:item_type, :item_id]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateAttachments < ActiveRecord::Migration
|
2
|
+
|
3
|
+
# Store application specific data for attachments a.k.a. uploaded files
|
4
|
+
def change
|
5
|
+
create_table :importable_attachments_attachments, :force => true do |t|
|
6
|
+
t.string :attachable_type
|
7
|
+
t.string :attachable_id # project might be using alpha-numeric IDs
|
8
|
+
t.string :io_stream_file_name
|
9
|
+
t.string :io_stream_content_type
|
10
|
+
t.integer :io_stream_file_size, :limit => 8
|
11
|
+
t.datetime :io_stream_updated_at
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
add_index :importable_attachments_attachments, [:attachable_type, :attachable_id], name: 'idx_importable_attachments_on_attachable_type_and_id'
|
16
|
+
add_index :importable_attachments_attachments, :io_stream_file_name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'importable_attachments/version'
|
6
|
+
#Bundler.require(:default, :development)
|
7
|
+
|
8
|
+
REQUIREMENTS = {
|
9
|
+
runtime: {
|
10
|
+
:'haml-rails' => ['~> 0.4'],
|
11
|
+
paper_trail: ['~> 2.7.1'],
|
12
|
+
paperclip: ['~> 3.4.2'],
|
13
|
+
configuration: ['~> 1.3.2'],
|
14
|
+
smarter_dates: ['~> 0.2.12'],
|
15
|
+
:'ruby-filemagic' => ['~> 0.4.2'],
|
16
|
+
:'rspec-paper_trail' => ['~> 0.0.10'],
|
17
|
+
:'rails-mark_requirements' => ['~> 0.0.1'],
|
18
|
+
:'rails-alpha_numeric_validator' => ['~> 0.1.1'],
|
19
|
+
formtastic: ['~> 2.2.1'],
|
20
|
+
remotipart: ['~> 1.0.5'],
|
21
|
+
roo: ['~> 1.11.2'],
|
22
|
+
rails: ['~> 3.2.13'],
|
23
|
+
:'activerecord-import' => ['~> 0.3.1'],
|
24
|
+
:'coffee-script' => ['~> 2.2.0'],
|
25
|
+
:'coffee-rails' => ['~> 3.2.2'] }, # coffee-rails is needed for <= 3.0.x
|
26
|
+
development: {
|
27
|
+
bundler: ['~> 1.3.0'],
|
28
|
+
rake: ['>= 0'],
|
29
|
+
sqlite3: ['~> 1.3.7'],
|
30
|
+
debugger: ['~> 1.5.0'],
|
31
|
+
rspec: ['~> 2.13.0'],
|
32
|
+
mocha: ['~> 0.13.0'],
|
33
|
+
database_cleaner: ['~> 1.0.1'],
|
34
|
+
machinist: ['~> 2.0.0'],
|
35
|
+
:'rspec-rails' => ['~> 2.13.0'],
|
36
|
+
:'cucumber-rails' => ['~> 1.3.1'],
|
37
|
+
poltergeist: ['< 1.1.0'],
|
38
|
+
capybara: ['< 2.0.0'],
|
39
|
+
launchy: ['~> 2.3.0'],
|
40
|
+
valid_attribute: ['~> 1.3.1'] }
|
41
|
+
}
|
42
|
+
|
43
|
+
Gem::Specification.new do |spec|
|
44
|
+
spec.name = 'importable_attachments'
|
45
|
+
spec.version = ImportableAttachments::VERSION
|
46
|
+
spec.authors = ['Paul Belt']
|
47
|
+
spec.email = %w(saprb@channing.harvard.edu)
|
48
|
+
spec.description = %q{Easier upload management for ActiveRecord}
|
49
|
+
spec.summary = %q{upload, save-to-disk, attach-to-model_instance, importing}
|
50
|
+
spec.homepage = 'https://github.com/belt/importable_attachments'
|
51
|
+
spec.license = 'MIT'
|
52
|
+
|
53
|
+
spec.files = `git ls-files`.split($/)
|
54
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
55
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
56
|
+
spec.require_paths = %w(lib)
|
57
|
+
|
58
|
+
spec.requirements = %w(libmagic)
|
59
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 1.9.2')
|
60
|
+
spec.required_rubygems_version = Gem::Requirement.new('>= 0') if spec.respond_to? :required_rubygems_version=
|
61
|
+
|
62
|
+
[:runtime, :development].each do |mode|
|
63
|
+
REQUIREMENTS[mode].each do |req,ver|
|
64
|
+
if spec.respond_to? :specification_version
|
65
|
+
spec.specification_version = 3
|
66
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0')
|
67
|
+
if mode == :runtime
|
68
|
+
spec.add_runtime_dependency req.to_s, ver
|
69
|
+
else
|
70
|
+
spec.add_development_dependency req.to_s, ver
|
71
|
+
end
|
72
|
+
else
|
73
|
+
spec.add_dependency req.to_s, ver
|
74
|
+
end
|
75
|
+
else
|
76
|
+
spec.add_dependency req.to_s, ver
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rails/generators/active_record/migration'
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
module ImportableAttachments
|
5
|
+
# copies configuration file for configuration.gem
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
extend ActiveRecord::Generators::Migration
|
9
|
+
|
10
|
+
source_root File.expand_path('../templates', __FILE__)
|
11
|
+
class_option :with_string_ids, type: :boolean, default: true, desc: 'versions.type_id as string (vs integer)'
|
12
|
+
|
13
|
+
# paperclip-3.3.x seems to require this
|
14
|
+
# paperclip-3.4.x seems to have broken this
|
15
|
+
class_option :with_revision_in_filename, type: :boolean, default: false, desc: 'filename on system to include version-number'
|
16
|
+
|
17
|
+
class_option :'skip-migrations', type: :boolean, default: false, desc: 'do not generate migrations'
|
18
|
+
class_option :force, type: :boolean, default: false, desc: 'force generation migrations'
|
19
|
+
|
20
|
+
desc 'Runs rspec:paper_trail:install'
|
21
|
+
|
22
|
+
def generate_rspec_paper_trail_install
|
23
|
+
return if skip_migrations?
|
24
|
+
cli_opts = options.select { |key, val| val }.map { |key, val| val ? "--#{key}" : val.join(",") }
|
25
|
+
cmd = 'rspec:paper_trail:install ' + cli_opts.join(" ")
|
26
|
+
generate cmd
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'Generates updated rspec:paper_trail:install config'
|
30
|
+
|
31
|
+
def generate_updated_rspec_paper_trail_config
|
32
|
+
template 'features/versioning.rb', 'config/features/versioning.rb'
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Runs smarter_dates:install'
|
36
|
+
|
37
|
+
def generate_smarter_dates_install
|
38
|
+
cli_opts = options.select { |key, val| val }.map { |key, val| val ? "--#{key}" : val.join(",") }
|
39
|
+
generate 'smarter_dates:install ' + cli_opts.join(" ")
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Generates initialization files.'
|
43
|
+
|
44
|
+
def generate_configuration_files
|
45
|
+
template 'features/attachments.rb.erb', 'config/features/attachments.rb'
|
46
|
+
copy_file 'initializers/paperclip.rb', 'config/initializers/paperclip.rb'
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'Augments spec/spec_helper.rb for formtastic deployment'
|
50
|
+
|
51
|
+
def augment_spec_helper
|
52
|
+
insert_into_file 'config/environments/production.rb', ' config.assets.precompile += %w(ie6.css ie7.css)', after: "# config.assets.precompile += %w( search.js )\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def skip_migrations?
|
58
|
+
return true if options.send(:'skip-migrations')
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
def use_versioned_filename?
|
63
|
+
options.with_revision_in_filename?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Configuration.for('attachments') do
|
2
|
+
enabled true
|
3
|
+
include_revision_in_filename <%= use_versioned_filename? %>
|
4
|
+
path ":rails_root/public/system/:rails_env/:style/:attachable_klass/:id_partition/:basename.:extension"
|
5
|
+
url ['development', 'test'].include?(Rails.env) ? "/attachments/:id/download" : "/system/:rails_env/:style/:attachable_klass/:id_partition/:basename.:extension"
|
6
|
+
end
|
7
|
+
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Configuration.for('versioning') do
|
2
|
+
enabled true
|
3
|
+
validate_item_type_constants false
|
4
|
+
path ':rails_root/public/system/:rails_env/:style/:attachable_klass/:id_partition/:basename.:stream_version.:extension'
|
5
|
+
url %w(development test).include?(Rails.env) ? '/attachments/:id/download' : '/system/:rails_env/:style/:attachable_klass/:id_partition/:basename.:stream_version.:extension'
|
6
|
+
end
|
7
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Paperclip.interpolates :stream_version do |attachment, _|
|
2
|
+
attachment.instance.revision_number
|
3
|
+
end
|
4
|
+
|
5
|
+
Paperclip.interpolates :attachable_klass do |attachment, _|
|
6
|
+
attachable_type = attachment.instance.attachable_type
|
7
|
+
attachable_type && attachable_type.respond_to?(:tableize) ? attachable_type.tableize : '.'
|
8
|
+
end
|
9
|
+
|
10
|
+
Paperclip.interpolates :rails_env do |_, _|
|
11
|
+
Rails.env
|
12
|
+
end
|
13
|
+
|
14
|
+
# brew on darwin
|
15
|
+
if File.directory?(File.join("", 'usr', 'local', 'bin'))
|
16
|
+
Paperclip.options[:command_path] = '/usr/local/bin'
|
17
|
+
|
18
|
+
# macports on darwin
|
19
|
+
elsif File.directory?(File.join("", 'opt', 'local', 'bin'))
|
20
|
+
Paperclip.options[:command_path] = '/opt/local/bin'
|
21
|
+
|
22
|
+
# "disabled" macports due to brew on darwin
|
23
|
+
elsif File.directory?(File.join("", 'opt', 'local.brew', 'bin'))
|
24
|
+
Paperclip.options[:command_path] = '/opt/local.brew/bin'
|
25
|
+
else
|
26
|
+
raise RuntimeError, 'can not locate identify binary'
|
27
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module ImportableAttachments::Base
|
2
|
+
module ClassMethods
|
3
|
+
|
4
|
+
# :call-seq:
|
5
|
+
# has_importable_attachment opts
|
6
|
+
#
|
7
|
+
# = opts
|
8
|
+
# :import_method
|
9
|
+
# :import_into
|
10
|
+
# :spreadsheet_columns
|
11
|
+
|
12
|
+
def has_importable_attachment(options)
|
13
|
+
lopt = {import_method: :import_rows}
|
14
|
+
lopt.merge! options
|
15
|
+
|
16
|
+
validate_importable_attachment_options lopt
|
17
|
+
install_importable_attachment_options lopt
|
18
|
+
install_importable_attachment_associations
|
19
|
+
install_importable_attachment_validations
|
20
|
+
install_importable_attachment_assignment_protection
|
21
|
+
|
22
|
+
include InstanceMethods
|
23
|
+
|
24
|
+
# for assigning attachment to new record
|
25
|
+
after_create :import_attachment
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate_importable_attachment_options(options)
|
29
|
+
[:spreadsheet_columns, :import_into].each do |sym|
|
30
|
+
raise RuntimeError, "has_importable_attachment: needs :#{sym}" unless options.has_key? sym
|
31
|
+
end
|
32
|
+
|
33
|
+
unless options[:spreadsheet_columns].is_a?(Enumerable)
|
34
|
+
raise RuntimeError, 'has_importable_attachment: :spreadsheet_columns must be Enumerable'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def install_importable_attachment_options(options)
|
39
|
+
[:import_method, :import_into, :spreadsheet_columns].each do |sym|
|
40
|
+
cattr_accessor sym
|
41
|
+
self.send("#{sym}=".to_sym, options[sym])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def install_importable_attachment_associations
|
46
|
+
has_one :attachment, :dependent => :nullify, :as => :attachable
|
47
|
+
delegate :io_stream, :to => :attachment, :prefix => true
|
48
|
+
delegate :io_stream_url, :to => :attachment, :prefix => true
|
49
|
+
delegate :io_stream_file_name, :to => :attachment, :prefix => true
|
50
|
+
end
|
51
|
+
|
52
|
+
def install_importable_attachment_validations
|
53
|
+
validates :attachment, :associated => true
|
54
|
+
validate do |record|
|
55
|
+
if @columns_not_found
|
56
|
+
invalid_attachment_error "column(s) not found: #{@columns_not_found}"
|
57
|
+
end
|
58
|
+
if !@row_errors.blank?
|
59
|
+
invalid_attachment_error "failed to import #{@row_errors.length} record(s)"
|
60
|
+
@row_errors.each {|row| attachment.errors.add(:base, row)}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# These go in the class calling has_importable_attachment as they are
|
65
|
+
# dependent on mime-type expectations
|
66
|
+
#validates_with CsvValidator, :if => Proc.new {|model| model.attachment.present?}
|
67
|
+
#validates_with ExcelValidator, :if => Proc.new {|model| model.attachment.present?}
|
68
|
+
end
|
69
|
+
|
70
|
+
def install_importable_attachment_assignment_protection
|
71
|
+
attr_accessible :attachment, :attachment_attributes, :attachment_id
|
72
|
+
accepts_nested_attributes_for :attachment, :allow_destroy => true,
|
73
|
+
:reject_if => :all_blank
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
module InstanceMethods
|
78
|
+
# : call-seq:
|
79
|
+
# import_attachment
|
80
|
+
#
|
81
|
+
# imports an attachment of a given mime-type (data-stream to ruby),
|
82
|
+
# calls import_rows with a ruby data-store
|
83
|
+
#
|
84
|
+
# NOTE: this is a stub
|
85
|
+
|
86
|
+
def import_attachment
|
87
|
+
raise RuntimeError, '[importable_attachments] .import_attachment not implemented'
|
88
|
+
end
|
89
|
+
|
90
|
+
# : call-seq:
|
91
|
+
# import_rows params
|
92
|
+
#
|
93
|
+
# imports an attachment contents into :import_into association
|
94
|
+
#
|
95
|
+
# NOTE: this is a stub
|
96
|
+
|
97
|
+
def import_rows(*opts)
|
98
|
+
return unless self.attachment
|
99
|
+
logger.debug "[importable_attachments] .import_rows #{opts}"
|
100
|
+
raise RuntimeError, '[importable_attachments] .import_rows not implemented'
|
101
|
+
end
|
102
|
+
|
103
|
+
def invalid_attachment_error(msg)
|
104
|
+
attachment.errors.add(:base, msg)
|
105
|
+
errors.add(:attachment, 'invalid attachment')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|