importable_attachments 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|