importable_attachments 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/.gitignore +24 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +38 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +8 -0
  7. data/README.rdoc +3 -0
  8. data/Rakefile +29 -0
  9. data/app/assets/images/importable_attachments/.gitkeep +0 -0
  10. data/app/assets/images/importable_attachments/buttons/.htaccess +5 -0
  11. data/app/assets/images/importable_attachments/buttons/download_32.png +0 -0
  12. data/app/assets/images/importable_attachments/buttons/upload_32.png +0 -0
  13. data/app/assets/javascripts/importable_attachments/application.js +14 -0
  14. data/app/assets/javascripts/importable_attachments/attachments.coffee +41 -0
  15. data/app/assets/stylesheets/importable_attachments/application.css +14 -0
  16. data/app/assets/stylesheets/importable_attachments/attachments.css +4 -0
  17. data/app/assets/stylesheets/scaffold.css +56 -0
  18. data/app/controllers/importable_attachments/application_controller.rb +4 -0
  19. data/app/controllers/importable_attachments/attachments_controller.rb +190 -0
  20. data/app/controllers/importable_attachments/versions_controller.rb +87 -0
  21. data/app/helpers/importable_attachments/application_helper.rb +4 -0
  22. data/app/models/attachment.rb +24 -0
  23. data/app/models/importable_attachments/attachment.rb +143 -0
  24. data/app/models/importable_attachments/version.rb +50 -0
  25. data/app/validators/existing_class_validator.rb +17 -0
  26. data/app/validators/importable_attachments/csv_validator.rb +36 -0
  27. data/app/validators/importable_attachments/excel.rb +18 -0
  28. data/app/validators/importable_attachments/excel_validator.rb +18 -0
  29. data/app/views/importable_attachments/attachments/_attachment.html.haml +9 -0
  30. data/app/views/importable_attachments/attachments/_form.html.haml +22 -0
  31. data/app/views/importable_attachments/attachments/_nested_form.html.haml +20 -0
  32. data/app/views/importable_attachments/attachments/edit.html.haml +39 -0
  33. data/app/views/importable_attachments/attachments/index.html.haml +23 -0
  34. data/app/views/importable_attachments/attachments/index.xml.builder +23 -0
  35. data/app/views/importable_attachments/attachments/new.html.haml +10 -0
  36. data/app/views/importable_attachments/attachments/show.html.haml +43 -0
  37. data/app/views/importable_attachments/versions/_form.html.haml +25 -0
  38. data/app/views/importable_attachments/versions/edit.html.haml +7 -0
  39. data/app/views/importable_attachments/versions/index.html.haml +27 -0
  40. data/app/views/importable_attachments/versions/new.html.haml +5 -0
  41. data/app/views/importable_attachments/versions/show.html.haml +21 -0
  42. data/app/views/layouts/_version.html.haml +33 -0
  43. data/app/views/layouts/importable_attachments/application.html.haml +48 -0
  44. data/bin/set_lc.sh +47 -0
  45. data/config/database.yml +25 -0
  46. data/config/features/attachments.rb +8 -0
  47. data/config/features/mark_requirements.rb +3 -0
  48. data/config/features/smarter_dates.rb +3 -0
  49. data/config/features/versioning.rb +7 -0
  50. data/config/initializers/0_configuration.rb +7 -0
  51. data/config/initializers/formtastic.rb +76 -0
  52. data/config/initializers/generators.rb +10 -0
  53. data/config/initializers/paperclip.rb +27 -0
  54. data/config/locales/responders.en.yml +10 -0
  55. data/config/routes.rb +11 -0
  56. data/db/migrate/001_create_importable_attachments_versions.rb +14 -0
  57. data/db/migrate/100_create_attachments.rb +19 -0
  58. data/importable_attachments.gemspec +81 -0
  59. data/lib/generators/importable_attachments/install_generator.rb +66 -0
  60. data/lib/generators/importable_attachments/templates/features/attachments.rb.erb +7 -0
  61. data/lib/generators/importable_attachments/templates/features/versioning.rb +7 -0
  62. data/lib/generators/importable_attachments/templates/initializers/paperclip.rb +27 -0
  63. data/lib/importable_attachments/base.rb +108 -0
  64. data/lib/importable_attachments/blueprints.rb +9 -0
  65. data/lib/importable_attachments/engine.rb +8 -0
  66. data/lib/importable_attachments/importers/csv.rb +208 -0
  67. data/lib/importable_attachments/importers/excel.rb +37 -0
  68. data/lib/importable_attachments/importers.rb +7 -0
  69. data/lib/importable_attachments/version.rb +3 -0
  70. data/lib/importable_attachments.rb +9 -0
  71. data/lib/paperclip_processors/save_upload.rb +33 -0
  72. data/lib/tasks/importable_attachments_tasks.rake +4 -0
  73. data/script/rails +8 -0
  74. data/spec/attachments/books.csv +6 -0
  75. data/spec/attachments/books.txt +6 -0
  76. data/spec/attachments/books2.csv +4 -0
  77. data/spec/attachments/empty.csv +0 -0
  78. data/spec/attachments/failed_instances.csv +3 -0
  79. data/spec/attachments/invalid_headers.csv +3 -0
  80. data/spec/attachments/just_headers.csv +1 -0
  81. data/spec/attachments/mostly_empty.csv +2 -0
  82. data/spec/attachments/mostly_empty_copy.xls +0 -0
  83. data/spec/controllers/importable_attachments/attachments_controller_spec.rb +236 -0
  84. data/spec/controllers/importable_attachments/versions_controller_spec.rb +158 -0
  85. data/spec/dummy/README.rdoc +261 -0
  86. data/spec/dummy/Rakefile +7 -0
  87. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  88. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  89. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  90. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  91. data/spec/dummy/app/mailers/.gitkeep +0 -0
  92. data/spec/dummy/app/models/.gitkeep +0 -0
  93. data/spec/dummy/app/models/book.rb +13 -0
  94. data/spec/dummy/app/models/library.rb +54 -0
  95. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  96. data/spec/dummy/config/application.rb +65 -0
  97. data/spec/dummy/config/boot.rb +10 -0
  98. data/spec/dummy/config/database.yml +25 -0
  99. data/spec/dummy/config/environment.rb +5 -0
  100. data/spec/dummy/config/environments/development.rb +37 -0
  101. data/spec/dummy/config/environments/production.rb +67 -0
  102. data/spec/dummy/config/environments/test.rb +37 -0
  103. data/spec/dummy/config/initializers/0_configuration.rb +7 -0
  104. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  105. data/spec/dummy/config/initializers/inflections.rb +15 -0
  106. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  107. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  108. data/spec/dummy/config/initializers/session_store.rb +8 -0
  109. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  110. data/spec/dummy/config/locales/en.yml +5 -0
  111. data/spec/dummy/config/routes.rb +4 -0
  112. data/spec/dummy/config.ru +4 -0
  113. data/spec/dummy/db/migrate/101_create_libraries.rb +10 -0
  114. data/spec/dummy/db/migrate/102_create_books.rb +12 -0
  115. data/spec/dummy/db/schema.rb +57 -0
  116. data/spec/dummy/features/person_uploads_generic_file.feature +11 -0
  117. data/spec/dummy/features/step_definitions/person_uploads_generic_file_steps.rb +11 -0
  118. data/spec/dummy/features/step_definitions/web_steps.rb +211 -0
  119. data/spec/dummy/features/support/capybara.rb +6 -0
  120. data/spec/dummy/features/support/database_cleaner.rb +26 -0
  121. data/spec/dummy/features/support/developer_helpers.rb +47 -0
  122. data/spec/dummy/features/support/env.rb +53 -0
  123. data/spec/dummy/features/support/paths.rb +33 -0
  124. data/spec/dummy/features/support/poltergeist.rb +1 -0
  125. data/spec/dummy/features/support/selectors.rb +39 -0
  126. data/spec/dummy/features/support/transactional_fixtures.rb +14 -0
  127. data/spec/dummy/lib/assets/.gitkeep +0 -0
  128. data/spec/dummy/log/.gitkeep +0 -0
  129. data/spec/dummy/public/404.html +38 -0
  130. data/spec/dummy/public/422.html +38 -0
  131. data/spec/dummy/public/500.html +36 -0
  132. data/spec/dummy/public/favicon.ico +0 -0
  133. data/spec/dummy/script/rails +6 -0
  134. data/spec/dummy/spec/support/.gitkeep +0 -0
  135. data/spec/dummy/spec/support/paperclip.rb +1 -0
  136. data/spec/models/importable_attachments/attachment_spec.rb +177 -0
  137. data/spec/models/importable_attachments/library_spec.rb +155 -0
  138. data/spec/models/importable_attachments/version_spec.rb +25 -0
  139. data/spec/routing/importable_attachments/versions_routing_spec.rb +43 -0
  140. data/spec/spec.opts +5 -0
  141. data/spec/spec_helper.rb +30 -0
  142. 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
+
@@ -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,3 @@
1
+ Configuration.for('mark_requirements') do
2
+ enabled true
3
+ end
@@ -0,0 +1,3 @@
1
+ Configuration.for('smarter_dates') do
2
+ enabled true
3
+ end
@@ -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,7 @@
1
+ Configuration.path = 'config/features'
2
+
3
+ # load feature configurations
4
+ features = Configuration.path.collect { |path| Dir.glob(File.join(path, '**')) }.flatten
5
+ features.each do |feature|
6
+ Configuration.load feature
7
+ end
@@ -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,10 @@
1
+ Rails.application.config.generators do |g|
2
+ g.view_specs false
3
+ g.helper_specs false
4
+ g.test_framework :rspec
5
+ g.fixture_replacement :machinist
6
+ g.orm :active_record
7
+ g.template_engine :haml
8
+ g.stylesheet_engine :sass
9
+ end
10
+
@@ -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
@@ -0,0 +1,9 @@
1
+ require 'machinist/active_record'
2
+
3
+ ImportableAttachments::Attachment.blueprint do
4
+ io_stream { File.new Rails.root.join('spec', 'attachments', 'mostly_empty_copy.xls') }
5
+ end
6
+
7
+ Version.blueprint do
8
+ end
9
+
@@ -0,0 +1,8 @@
1
+ require 'configuration'
2
+ require 'rails/alpha_numeric_validator'
3
+
4
+ module ImportableAttachments
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace ImportableAttachments
7
+ end
8
+ end