brightcontent-attachments 2.0.33 → 2.1.0

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/app/assets/javascripts/brightcontent/attachments.js.coffee +42 -0
  4. data/app/assets/stylesheets/brightcontent/attachments.css.scss +3 -0
  5. data/app/controllers/brightcontent/attachments_controller.rb +9 -6
  6. data/app/models/brightcontent/attachment.rb +17 -1
  7. data/app/views/brightcontent/attachments/_attachment.html.erb +16 -10
  8. data/app/views/brightcontent/base/_form_field_attachments.html.erb +9 -11
  9. data/app/views/brightcontent/base/_list_field_attachments.html.erb +4 -0
  10. data/brightcontent-attachments.gemspec +1 -1
  11. data/config/locales/brightcontent_attachements.en.yml +8 -0
  12. data/config/locales/brightcontent_attachements.nl.yml +8 -0
  13. data/config/routes.rb +1 -1
  14. data/db/migrate/20140203140819_add_position_to_attachments.rb +5 -0
  15. data/lib/brightcontent/attachments/attachable.rb +16 -0
  16. data/lib/brightcontent/attachments/engine.rb +1 -1
  17. data/lib/brightcontent/attachments/model_extensions.rb +16 -0
  18. data/lib/brightcontent/attachments.rb +6 -2
  19. data/lib/generators/brightcontent/attachments/install_generator.rb +0 -3
  20. data/script/rails +2 -2
  21. data/spec/dummy/config/application.rb +2 -6
  22. data/spec/dummy/config/environments/development.rb +1 -10
  23. data/spec/dummy/config/environments/production.rb +0 -4
  24. data/spec/dummy/config/environments/test.rb +1 -6
  25. data/spec/dummy/config/initializers/secret_token.rb +1 -1
  26. data/spec/dummy/db/migrate/20121206121725_create_brightcontent_admin_users.rb +1 -1
  27. data/spec/dummy/db/schema.rb +14 -13
  28. data/spec/features/attachments_spec.rb +5 -6
  29. data/spec/models/brightcontent/attachable_spec.rb +10 -8
  30. data/spec/models/brightcontent/attachment_spec.rb +19 -0
  31. data/vendor/assets/javascripts/spin.js +353 -0
  32. metadata +33 -28
  33. data/app/assets/javascripts/brightcontent/attachments.js +0 -14
  34. data/app/helpers/brightcontent/attachments_helper.rb +0 -4
  35. data/lib/brightcontent/attachable.rb +0 -15
  36. data/lib/brightcontent/attachment_model_extensions.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 31453eae643abc77863b353258667588ca9cbfb8
4
- data.tar.gz: 61d12130d8c1db3cec30990c81b5bb784437097e
3
+ metadata.gz: 9fe1f577211b1bff0afc4b534bcea4542074de68
4
+ data.tar.gz: 325702f3a132bf2655a27b0bc013699b191e4927
5
5
  SHA512:
6
- metadata.gz: 011ccfec559cfbf7d72d9f7f61b82ef56cffd5a84d136882a98889538615f37ec3a0ca91aff53b1bb08f3ae95092015400c6b02f8dd322570f41840f4bc0dc2a
7
- data.tar.gz: 714478bfc864a6842b5ec97e892cc3596e2697e32cd6ad98eeef9cf999f10f1552ea1b42f5425a0d652e9b14f65564e03266522cd94af79bf3c9f7cd3cbcad66
6
+ metadata.gz: 66247189162509cd49e45c686ae5ad59a260053110da12da42bb3f5ce975fef2d97918d8f2b1f0079ba8881c06c87676a33944c200d1fced267d188cec991c54
7
+ data.tar.gz: 83d89ffac4c3f21c62f0818c7d73ad35e3cbe1f32fa0cac70c302e2972ee58b644e80f70594eaad9bb641160b8a7800004dca1ac369ca85e7197e682cf578298
data/.gitignore CHANGED
@@ -8,3 +8,4 @@ spec/dummy/log/*.log
8
8
  spec/dummy/tmp/
9
9
  spec/dummy/.sass-cache
10
10
  vendor/bundle
11
+ bin/
@@ -0,0 +1,42 @@
1
+ #= require jquery-fileupload/basic
2
+ #= require spin
3
+
4
+ $ ->
5
+ request_url = $("#attachable_url").val()
6
+
7
+ spinner = new Spinner().spin()
8
+ $('#fileupload').fileupload
9
+ method: "PUT"
10
+ send: ->
11
+ spinner.spin $("#attachments-controls")[0]
12
+ $("#attachments *").attr disabled: true
13
+ $("#fileupload").attr disabled: true
14
+ $("#attachments-controls").css opacity: 0.5
15
+
16
+ done: (e, data) ->
17
+ $.get request_url, (attachments_view) ->
18
+ $('#attachments').html attachments_view
19
+ spinner.stop()
20
+ $("#fileupload").attr disabled: false
21
+ $("#attachments-controls").css opacity: 1
22
+
23
+
24
+ $("#attachments").on "click", ".delete", ->
25
+ el = $(this).parents(".attachment")
26
+ spinner.spin el[0]
27
+ el.css opacity: 0.5
28
+ el.find("*").attr disabled: true
29
+ $.ajax
30
+ method: "DELETE"
31
+ url: $(this).attr "href"
32
+ success: -> el.remove()
33
+ false
34
+
35
+ $("#attachments").sortable
36
+ axis: "y"
37
+ cancel: "input,textarea,button,select,option,a"
38
+ distance: 5
39
+ update: ->
40
+ $.post "#{request_url}/reposition", positions: ($("#attachments > *").map -> $(this).data "attachment-id").toArray()
41
+
42
+ $("#attachments").disableSelection()
@@ -0,0 +1,3 @@
1
+ #attachments .attachment {
2
+ cursor: move;
3
+ }
@@ -2,9 +2,8 @@ require_dependency "brightcontent/application_controller"
2
2
 
3
3
  module Brightcontent
4
4
  class AttachmentsController < ApplicationController
5
-
6
5
  def show
7
- @attachments = Attachment.where(attachable_type: params[:type].classify, attachable_id: params[:id])
6
+ @attachments = Attachment.for_attachable(params[:type], params[:id])
8
7
  render layout: false
9
8
  end
10
9
 
@@ -18,15 +17,19 @@ module Brightcontent
18
17
  end
19
18
 
20
19
  def destroy
21
- attachment = Attachment.destroy(params[:id])
22
- redirect_to attachment.attachable
20
+ Attachment.destroy params[:id]
21
+ head :no_content
22
+ end
23
+
24
+ def reposition
25
+ Attachment.for_attachable(params[:type], params[:id]).reposition! params[:positions]
26
+ head :no_content
23
27
  end
24
28
 
25
29
  private
26
30
 
27
31
  def attachment_params
28
- params.permit(:attachable_id, :attachable_type, :asset)
32
+ params.require(:attachment).permit(:attachable_id, :attachable_type, :asset)
29
33
  end
30
-
31
34
  end
32
35
  end
@@ -3,13 +3,26 @@ module Brightcontent
3
3
  belongs_to :attachable, polymorphic: true, :inverse_of => :attachments
4
4
  has_attached_file :asset, :styles => lambda {|attachment| attachment.instance.attachment_styles }
5
5
  before_post_process :resize_images
6
+ before_create :set_position
6
7
 
7
- default_scope order("id")
8
+ default_scope { order("position, id") }
9
+ scope :for_attachable, -> type, id { where(attachable_type: type.classify, attachable_id: id) }
8
10
 
9
11
  delegate :url, to: :asset
10
12
 
13
+ validates_attachment_content_type :asset, content_type: Brightcontent.attachment_content_types
14
+ validates :attachable, presence: true
11
15
  validates :asset, attachment_presence: true
12
16
 
17
+ def self.reposition!(positions)
18
+ positions.map! &:to_i
19
+ transaction do
20
+ all.each do |attachment|
21
+ attachment.update_column :position, positions.index(attachment.id)
22
+ end
23
+ end
24
+ end
25
+
13
26
  def attachment_styles
14
27
  default_attachment_styles.merge(user_defined_styles)
15
28
  end
@@ -34,5 +47,8 @@ module Brightcontent
34
47
  return false unless image?
35
48
  end
36
49
 
50
+ def set_position
51
+ self.position ||= self.class.for_attachable(attachable_type, attachable_id).maximum(:position).to_i + 1
52
+ end
37
53
  end
38
54
  end
@@ -1,10 +1,16 @@
1
- <%= div_for attachment do %>
2
- <% if attachment.image? %>
3
- <%= image_tag attachment.url(:brightcontent) %>
4
- <%= link_to "Insert", nil, class: "insert insert_image btn btn-mini", data: { insert_image: attachment.url(:main) } %>
5
- <% else %>
6
- <div class="attachment-file"><%= attachment.asset_file_name %></div>
7
- <%= link_to "Insert", nil, class: "insert insert_link btn btn-mini", data: { insert_url: attachment.url(:original), insert_name: attachment.asset_file_name } %>
8
- <% end %>
9
- <%= link_to "Delete", destroy_attachment_path(attachment.id), method: :delete, confirm: "Are you sure?", class: "delete btn btn-danger btn-mini" %>
10
- <% end %>
1
+ <li class="list-group-item attachment" data-attachment-id="<%= attachment.id %>">
2
+ <div class="media">
3
+ <% if attachment.image? %>
4
+ <%= image_tag attachment.url(:brightcontent), class: "media-object pull-left" %>
5
+ <% end %>
6
+ <div class="media-body">
7
+ <h4 class="attachment-file media-heading"><%= attachment.asset_file_name %></h4>
8
+ <% if attachment.image? %>
9
+ <%= link_to "Insert", nil, class: "insert insert_image btn btn-primary btn-xs", data: { insert_image: attachment.url(:main) } %>
10
+ <% else %>
11
+ <%= link_to "Insert", nil, class: "insert insert_link btn btn-primary btn-xs", data: { insert_url: attachment.url(:original), insert_name: attachment.asset_file_name } %>
12
+ <% end %>
13
+ <%= link_to "Delete", destroy_attachment_path(attachment.id), class: "delete btn btn-danger btn-xs", method: "delete" %>
14
+ </div>
15
+ </div>
16
+ </li>
@@ -1,18 +1,16 @@
1
- <div class="control-group optional">
2
- <label class="optional control-label">Attachments</label>
3
- <div class="controls">
1
+ <div class="control-group">
2
+ <label class="control-label"><%=Brightcontent::Attachment.model_name.human.pluralize%></label>
3
+ <div class="controls" id="attachments-controls">
4
4
  <% if item.persisted? %>
5
- <div id="attachments" class="clearfix">
5
+ <ul class="media-list" id="attachments">
6
6
  <%= render item.attachments %>
7
- </div>
8
-
9
- <input id="fileupload" type="file" name="asset" data-url="<%= new_attachment_path %>" multiple>
10
- <%= hidden_field_tag "attachable_id", item.id %>
11
- <%= hidden_field_tag "attachable_type", item.class.to_s %>
7
+ </ul>
8
+ <input id="fileupload" type="file" name="attachment[asset]" data-url="<%= new_attachment_path %>" class="form-control" multiple>
9
+ <%= hidden_field_tag "attachment[attachable_id]", item.id %>
10
+ <%= hidden_field_tag "attachment[attachable_type]", item.class.to_s %>
12
11
  <%= hidden_field_tag "attachable_url", attachments_path(item.class.to_s, item.id) %>
13
-
14
12
  <% else %>
15
- First save to enable uploads
13
+ <p class="form-control-static"><%= t('brightcontent.save_first')%></p>
16
14
  <% end %>
17
15
  </div>
18
16
  </div>
@@ -0,0 +1,4 @@
1
+ <% if item.attachments.any? %>
2
+ <span class="glyphicon glyphicon-paperclip"></span>
3
+ <%= item.attachments.count %>
4
+ <% end %>
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.require_paths = ["lib"]
17
17
 
18
18
  s.add_dependency "brightcontent-core", version
19
- s.add_dependency "paperclip"
19
+ s.add_dependency "paperclip", ">= 3.0.0"
20
20
  s.add_dependency "jquery-fileupload-rails"
21
21
 
22
22
  s.add_development_dependency "sqlite3"
@@ -0,0 +1,8 @@
1
+ en:
2
+ activerecord:
3
+ models:
4
+ brightcontent/attachment: Attachment
5
+
6
+ brightcontent:
7
+ save_first: First save to enable uploads
8
+ insert: Insert
@@ -0,0 +1,8 @@
1
+ nl:
2
+ activerecord:
3
+ models:
4
+ brightcontent/attachment: Bijlage
5
+
6
+ brightcontent:
7
+ save_first: Bewaar het item eerst voordat je kunt uploaden.
8
+ insert: Invoegen
data/config/routes.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  Brightcontent::Engine.routes.draw do
2
- # TODO: put instead of create
3
2
  get 'attachments/:type/:id' => 'attachments#show', as: :attachments
3
+ post 'attachments/:type/:id/reposition' => 'attachments#reposition'
4
4
  put 'attachments' => 'attachments#create', as: :new_attachment
5
5
  delete 'attachments/:id' => 'attachments#destroy', as: :destroy_attachment
6
6
  end
@@ -0,0 +1,5 @@
1
+ class AddPositionToAttachments < ActiveRecord::Migration
2
+ def change
3
+ add_column :brightcontent_attachments, :position, :integer
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ module Brightcontent
2
+ module Attachments
3
+ module Attachable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ add_brightcontent_column :attachments
8
+ has_many :attachments, as: :attachable, dependent: :destroy, class_name: Brightcontent::Attachment, inverse_of: :attachable
9
+ end
10
+
11
+ def attachment
12
+ attachments.first
13
+ end
14
+ end
15
+ end
16
+ end
@@ -3,7 +3,7 @@ module Brightcontent
3
3
  class Engine < ::Rails::Engine
4
4
  initializer "Add attachments class method" do
5
5
  ActiveSupport.on_load(:active_record) do
6
- include AttachmentModelExtensions
6
+ include ModelExtensions
7
7
  end
8
8
  end
9
9
  end
@@ -0,0 +1,16 @@
1
+ module Brightcontent
2
+ module Attachments
3
+ module ModelExtensions
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ attr_reader :attachment_styles
8
+
9
+ def has_attached_files(styles)
10
+ include ::Brightcontent::Attachments::Attachable
11
+ @attachment_styles = styles
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -5,9 +5,13 @@ require "jquery-fileupload-rails"
5
5
  require "brightcontent/attachments/engine"
6
6
 
7
7
  module Brightcontent
8
- autoload :Attachable, 'brightcontent/attachable'
9
- autoload :AttachmentModelExtensions, 'brightcontent/attachment_model_extensions'
8
+ register_extension 'attachments'
9
+
10
+ mattr_reader :attachment_content_types
11
+ @@attachment_content_types = [/\Aimage/, "application/pdf"]
10
12
 
11
13
  module Attachments
14
+ autoload :Attachable, 'brightcontent/attachments/attachable'
15
+ autoload :ModelExtensions, 'brightcontent/attachments/model_extensions'
12
16
  end
13
17
  end
@@ -2,13 +2,10 @@ module Brightcontent
2
2
  module Attachments
3
3
  module Generators
4
4
  class InstallGenerator < Rails::Generators::Base
5
-
6
5
  desc "Install migrations for Brightcontent Attachments"
7
-
8
6
  def copy_migrations
9
7
  rake "brightcontent_attachments_engine:install:migrations"
10
8
  end
11
-
12
9
  end
13
10
  end
14
11
  end
data/script/rails CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
3
 
4
- ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
- ENGINE_PATH = File.expand_path('../../lib/brightcontent/assets/engine', __FILE__)
4
+ ENGINE_ROOT = File.expand_path('../../../core', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../../core/lib/brightcontent/engine', __FILE__)
6
6
 
7
7
  require 'rails/all'
8
8
  require 'rails/engine/commands'
@@ -43,15 +43,11 @@ module Dummy
43
43
  # like if you have constraints or database-specific column types
44
44
  # config.active_record.schema_format = :sql
45
45
 
46
- # Enforce whitelist mode for mass assignment.
47
- # This will create an empty whitelist of attributes available for mass-assignment for all models
48
- # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
49
- # parameters by using an attr_accessible or attr_protected declaration.
50
- config.active_record.whitelist_attributes = false
51
-
52
46
  # Enable the asset pipeline
53
47
  config.assets.enabled = true
54
48
 
49
+ # config.i18n.enforce_available_locales = true
50
+
55
51
  # Version of your assets, change this if you want to expire all your assets
56
52
  config.assets.version = '1.0'
57
53
  end
@@ -1,14 +1,12 @@
1
1
  Dummy::Application.configure do
2
2
  # Settings specified here will take precedence over those in config/application.rb
3
+ config.eager_load = false
3
4
 
4
5
  # In the development environment your application's code is reloaded on
5
6
  # every request. This slows down response time but is perfect for development
6
7
  # since you don't have to restart the web server when you make code changes.
7
8
  config.cache_classes = false
8
9
 
9
- # Log error messages when you accidentally call methods on nil.
10
- config.whiny_nils = true
11
-
12
10
  # Show full error reports and disable caching
13
11
  config.consider_all_requests_local = true
14
12
  config.action_controller.perform_caching = false
@@ -22,13 +20,6 @@ Dummy::Application.configure do
22
20
  # Only use best-standards-support built into browsers
23
21
  config.action_dispatch.best_standards_support = :builtin
24
22
 
25
- # Raise exception on mass assignment protection for Active Record models
26
- config.active_record.mass_assignment_sanitizer = :strict
27
-
28
- # Log the query plan for queries taking more than this (works
29
- # with SQLite, MySQL, and PostgreSQL)
30
- config.active_record.auto_explain_threshold_in_seconds = 0.5
31
-
32
23
  # Do not compress assets
33
24
  config.assets.compress = false
34
25
 
@@ -60,8 +60,4 @@ Dummy::Application.configure do
60
60
 
61
61
  # Send deprecation notices to registered listeners
62
62
  config.active_support.deprecation = :notify
63
-
64
- # Log the query plan for queries taking more than this (works
65
- # with SQLite, MySQL, and PostgreSQL)
66
- # config.active_record.auto_explain_threshold_in_seconds = 0.5
67
63
  end
@@ -1,5 +1,6 @@
1
1
  Dummy::Application.configure do
2
2
  # Settings specified here will take precedence over those in config/application.rb
3
+ config.eager_load = false
3
4
 
4
5
  # The test environment is used exclusively to run your application's
5
6
  # test suite. You never need to work with it otherwise. Remember that
@@ -11,9 +12,6 @@ Dummy::Application.configure do
11
12
  config.serve_static_assets = true
12
13
  config.static_cache_control = "public, max-age=3600"
13
14
 
14
- # Log error messages when you accidentally call methods on nil
15
- config.whiny_nils = true
16
-
17
15
  # Show full error reports and disable caching
18
16
  config.consider_all_requests_local = true
19
17
  config.action_controller.perform_caching = false
@@ -29,9 +27,6 @@ Dummy::Application.configure do
29
27
  # ActionMailer::Base.deliveries array.
30
28
  config.action_mailer.delivery_method = :test
31
29
 
32
- # Raise exception on mass assignment protection for Active Record models
33
- config.active_record.mass_assignment_sanitizer = :strict
34
-
35
30
  # Print deprecation notices to the stderr
36
31
  config.active_support.deprecation = :stderr
37
32
  end
@@ -4,4 +4,4 @@
4
4
  # If you change this key, all old signed cookies will become invalid!
5
5
  # Make sure the secret is at least 30 characters and all random,
6
6
  # no regular words or you'll be exposed to dictionary attacks.
7
- Dummy::Application.config.secret_token = '1582af16879d84e4319aa02ea51964c7c27576e6468838ea1bcadf1286623d44e9117613a747386fde1bc2253a9a49c291a2c100fec64ae5c2cc5c75efa553ef'
7
+ Dummy::Application.config.secret_key_base = '1582af16879d84e4319aa02ea51964c7c27576e6468838ea1bcadf1286623d44e9117613a747386fde1bc2253a9a49c291a2c100fec64ae5c2cc5c75efa553ef'
@@ -7,6 +7,6 @@ class CreateBrightcontentAdminUsers < ActiveRecord::Migration
7
7
  t.timestamps
8
8
  end
9
9
 
10
- Brightcontent::AdminUser.create!(:email => 'admin@example.com', :password => 'password')
10
+ Brightcontent::AdminUser.create!(:email => 'admin@example.com', :password => 'password', :password_confirmation => 'password')
11
11
  end
12
12
  end
@@ -9,36 +9,37 @@
9
9
  # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
10
  # you'll amass, the slower it'll run and the greater likelihood for issues).
11
11
  #
12
- # It's strongly recommended to check this file into your version control system.
12
+ # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20121222172513) do
14
+ ActiveRecord::Schema.define(version: 20140203140819) do
15
15
 
16
- create_table "blogs", :force => true do |t|
16
+ create_table "blogs", force: true do |t|
17
17
  t.string "name"
18
18
  t.text "body"
19
- t.datetime "created_at", :null => false
20
- t.datetime "updated_at", :null => false
19
+ t.datetime "created_at", null: false
20
+ t.datetime "updated_at", null: false
21
21
  end
22
22
 
23
- create_table "brightcontent_admin_users", :force => true do |t|
23
+ create_table "brightcontent_admin_users", force: true do |t|
24
24
  t.string "email"
25
25
  t.string "password_digest"
26
- t.datetime "created_at", :null => false
27
- t.datetime "updated_at", :null => false
26
+ t.datetime "created_at", null: false
27
+ t.datetime "updated_at", null: false
28
28
  end
29
29
 
30
- create_table "brightcontent_attachments", :force => true do |t|
30
+ create_table "brightcontent_attachments", force: true do |t|
31
31
  t.integer "attachable_id"
32
32
  t.string "attachable_type"
33
33
  t.string "asset_file_name"
34
34
  t.string "asset_content_type"
35
35
  t.integer "asset_file_size"
36
36
  t.datetime "asset_updated_at"
37
- t.datetime "created_at", :null => false
38
- t.datetime "updated_at", :null => false
37
+ t.datetime "created_at", null: false
38
+ t.datetime "updated_at", null: false
39
+ t.integer "position"
39
40
  end
40
41
 
41
- add_index "brightcontent_attachments", ["attachable_id"], :name => "index_brightcontent_attachments_on_attachable_id"
42
- add_index "brightcontent_attachments", ["attachable_type"], :name => "index_brightcontent_attachments_on_attachable_type"
42
+ add_index "brightcontent_attachments", ["attachable_id"], name: "index_brightcontent_attachments_on_attachable_id"
43
+ add_index "brightcontent_attachments", ["attachable_type"], name: "index_brightcontent_attachments_on_attachable_type"
43
44
 
44
45
  end
@@ -7,7 +7,7 @@ feature "Attachments" do
7
7
 
8
8
  scenario "show message if item is not saved" do
9
9
  click_link "Blogs"
10
- click_link "Create new Blog"
10
+ click_link "Create new blog"
11
11
  page.should have_content "First save to enable uploads"
12
12
  end
13
13
 
@@ -21,21 +21,20 @@ feature "Attachments" do
21
21
  context "with image" do
22
22
  background do
23
23
  blog = create(:blog)
24
- @attachment = Brightcontent::Attachment.create!(:asset => Rails.root.join("public/rails.png").open)
25
- blog.attachments << @attachment
24
+ @attachment = blog.attachments.create!(:asset => Rails.root.join("public/rails.png").open)
26
25
  click_link "Blogs"
27
26
  click_link "Edit"
28
27
  end
29
28
 
30
29
  scenario "shows images" do
31
- page.should have_selector "#attachment_#{@attachment.id}"
30
+ page.should have_selector "[data-attachment-id=\"#{@attachment.id}\"]"
32
31
  end
33
32
 
34
33
  scenario "delete image" do
35
- within "#attachment_#{@attachment.id}" do
34
+ within "[data-attachment-id=\"#{@attachment.id}\"]" do
36
35
  click_link "Delete"
37
36
  end
38
- page.should_not have_selector "#attachment_#{@attachment.id}"
37
+ page.should_not have_selector "[data-attachment-id=\"#{@attachment.id}\"]"
39
38
  end
40
39
  end
41
40
  end
@@ -1,16 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module Brightcontent
4
- describe Attachable do
5
- subject { Blog }
6
- its(:brightcontent_columns) { should include "attachments" }
4
+ module Attachments
5
+ describe Attachable do
6
+ subject { Blog }
7
+ its(:brightcontent_columns) { should include "attachments" }
7
8
 
8
- it "should have a has_many relation to attachments" do
9
- Blog.reflect_on_association(:attachments).macro.should eq :has_many
10
- end
9
+ it "should have a has_many relation to attachments" do
10
+ Blog.reflect_on_association(:attachments).macro.should eq :has_many
11
+ end
11
12
 
12
- it "should have .attachment method" do
13
- Blog.new.should respond_to :attachment
13
+ it "should have .attachment method" do
14
+ Blog.new.should respond_to :attachment
15
+ end
14
16
  end
15
17
  end
16
18
  end
@@ -15,5 +15,24 @@ module Brightcontent
15
15
  its(:attachment_styles) { should == { test: "200x200", brightcontent: "100x100#", main: "200x200#" } }
16
16
  end
17
17
  end
18
+
19
+ describe ".reposition!" do
20
+ let!(:blog) { build_stubbed(:blog) }
21
+ let!(:attachment_1) { blog.attachments.create!(:asset => Rails.root.join("public/rails.png").open) }
22
+ let!(:attachment_2) { blog.attachments.create!(:asset => Rails.root.join("public/rails.png").open) }
23
+ let!(:attachment_3) { blog.attachments.create!(:asset => Rails.root.join("public/rails.png").open) }
24
+
25
+ it "reorders the attachments as specified" do
26
+ ids = [attachment_2.id, attachment_3.id, attachment_1.id]
27
+ Attachment.reposition! ids
28
+ blog.attachments.pluck(:id).should == ids
29
+ end
30
+
31
+ it "sets unspecified attachments' positions to nil" do
32
+ ids = [attachment_3.id, attachment_2.id]
33
+ Attachment.reposition! ids
34
+ attachment_1.reload.position.should be_nil
35
+ end
36
+ end
18
37
  end
19
38
  end
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Copyright (c) 2011-2013 Felix Gnass
3
+ * Licensed under the MIT license
4
+ */
5
+ (function(root, factory) {
6
+
7
+ /* CommonJS */
8
+ if (typeof exports == 'object') module.exports = factory()
9
+
10
+ /* AMD module */
11
+ else if (typeof define == 'function' && define.amd) define(factory)
12
+
13
+ /* Browser global */
14
+ else root.Spinner = factory()
15
+ }
16
+ (this, function() {
17
+ "use strict";
18
+
19
+ var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
20
+ , animations = {} /* Animation rules keyed by their name */
21
+ , useCssAnimations /* Whether to use CSS animations or setTimeout */
22
+
23
+ /**
24
+ * Utility function to create elements. If no tag name is given,
25
+ * a DIV is created. Optionally properties can be passed.
26
+ */
27
+ function createEl(tag, prop) {
28
+ var el = document.createElement(tag || 'div')
29
+ , n
30
+
31
+ for(n in prop) el[n] = prop[n]
32
+ return el
33
+ }
34
+
35
+ /**
36
+ * Appends children and returns the parent.
37
+ */
38
+ function ins(parent /* child1, child2, ...*/) {
39
+ for (var i=1, n=arguments.length; i<n; i++)
40
+ parent.appendChild(arguments[i])
41
+
42
+ return parent
43
+ }
44
+
45
+ /**
46
+ * Insert a new stylesheet to hold the @keyframe or VML rules.
47
+ */
48
+ var sheet = (function() {
49
+ var el = createEl('style', {type : 'text/css'})
50
+ ins(document.getElementsByTagName('head')[0], el)
51
+ return el.sheet || el.styleSheet
52
+ }())
53
+
54
+ /**
55
+ * Creates an opacity keyframe animation rule and returns its name.
56
+ * Since most mobile Webkits have timing issues with animation-delay,
57
+ * we create separate rules for each line/segment.
58
+ */
59
+ function addAnimation(alpha, trail, i, lines) {
60
+ var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-')
61
+ , start = 0.01 + i/lines * 100
62
+ , z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
63
+ , prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
64
+ , pre = prefix && '-' + prefix + '-' || ''
65
+
66
+ if (!animations[name]) {
67
+ sheet.insertRule(
68
+ '@' + pre + 'keyframes ' + name + '{' +
69
+ '0%{opacity:' + z + '}' +
70
+ start + '%{opacity:' + alpha + '}' +
71
+ (start+0.01) + '%{opacity:1}' +
72
+ (start+trail) % 100 + '%{opacity:' + alpha + '}' +
73
+ '100%{opacity:' + z + '}' +
74
+ '}', sheet.cssRules.length)
75
+
76
+ animations[name] = 1
77
+ }
78
+
79
+ return name
80
+ }
81
+
82
+ /**
83
+ * Tries various vendor prefixes and returns the first supported property.
84
+ */
85
+ function vendor(el, prop) {
86
+ var s = el.style
87
+ , pp
88
+ , i
89
+
90
+ prop = prop.charAt(0).toUpperCase() + prop.slice(1)
91
+ for(i=0; i<prefixes.length; i++) {
92
+ pp = prefixes[i]+prop
93
+ if(s[pp] !== undefined) return pp
94
+ }
95
+ if(s[prop] !== undefined) return prop
96
+ }
97
+
98
+ /**
99
+ * Sets multiple style properties at once.
100
+ */
101
+ function css(el, prop) {
102
+ for (var n in prop)
103
+ el.style[vendor(el, n)||n] = prop[n]
104
+
105
+ return el
106
+ }
107
+
108
+ /**
109
+ * Fills in default values.
110
+ */
111
+ function merge(obj) {
112
+ for (var i=1; i < arguments.length; i++) {
113
+ var def = arguments[i]
114
+ for (var n in def)
115
+ if (obj[n] === undefined) obj[n] = def[n]
116
+ }
117
+ return obj
118
+ }
119
+
120
+ /**
121
+ * Returns the absolute page-offset of the given element.
122
+ */
123
+ function pos(el) {
124
+ var o = { x:el.offsetLeft, y:el.offsetTop }
125
+ while((el = el.offsetParent))
126
+ o.x+=el.offsetLeft, o.y+=el.offsetTop
127
+
128
+ return o
129
+ }
130
+
131
+ /**
132
+ * Returns the line color from the given string or array.
133
+ */
134
+ function getColor(color, idx) {
135
+ return typeof color == 'string' ? color : color[idx % color.length]
136
+ }
137
+
138
+ // Built-in defaults
139
+
140
+ var defaults = {
141
+ lines: 12, // The number of lines to draw
142
+ length: 7, // The length of each line
143
+ width: 5, // The line thickness
144
+ radius: 10, // The radius of the inner circle
145
+ rotate: 0, // Rotation offset
146
+ corners: 1, // Roundness (0..1)
147
+ color: '#000', // #rgb or #rrggbb
148
+ direction: 1, // 1: clockwise, -1: counterclockwise
149
+ speed: 1, // Rounds per second
150
+ trail: 100, // Afterglow percentage
151
+ opacity: 1/4, // Opacity of the lines
152
+ fps: 20, // Frames per second when using setTimeout()
153
+ zIndex: 2e9, // Use a high z-index by default
154
+ className: 'spinner', // CSS class to assign to the element
155
+ top: 'auto', // center vertically
156
+ left: 'auto', // center horizontally
157
+ position: 'relative' // element position
158
+ }
159
+
160
+ /** The constructor */
161
+ function Spinner(o) {
162
+ if (typeof this == 'undefined') return new Spinner(o)
163
+ this.opts = merge(o || {}, Spinner.defaults, defaults)
164
+ }
165
+
166
+ // Global defaults that override the built-ins:
167
+ Spinner.defaults = {}
168
+
169
+ merge(Spinner.prototype, {
170
+
171
+ /**
172
+ * Adds the spinner to the given target element. If this instance is already
173
+ * spinning, it is automatically removed from its previous target b calling
174
+ * stop() internally.
175
+ */
176
+ spin: function(target) {
177
+ this.stop()
178
+
179
+ var self = this
180
+ , o = self.opts
181
+ , el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex})
182
+ , mid = o.radius+o.length+o.width
183
+ , ep // element position
184
+ , tp // target position
185
+
186
+ if (target) {
187
+ target.insertBefore(el, target.firstChild||null)
188
+ tp = pos(target)
189
+ ep = pos(el)
190
+ css(el, {
191
+ left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : parseInt(o.left, 10) + mid) + 'px',
192
+ top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid) + 'px'
193
+ })
194
+ }
195
+
196
+ el.setAttribute('role', 'progressbar')
197
+ self.lines(el, self.opts)
198
+
199
+ if (!useCssAnimations) {
200
+ // No CSS animation support, use setTimeout() instead
201
+ var i = 0
202
+ , start = (o.lines - 1) * (1 - o.direction) / 2
203
+ , alpha
204
+ , fps = o.fps
205
+ , f = fps/o.speed
206
+ , ostep = (1-o.opacity) / (f*o.trail / 100)
207
+ , astep = f/o.lines
208
+
209
+ ;(function anim() {
210
+ i++;
211
+ for (var j = 0; j < o.lines; j++) {
212
+ alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)
213
+
214
+ self.opacity(el, j * o.direction + start, alpha, o)
215
+ }
216
+ self.timeout = self.el && setTimeout(anim, ~~(1000/fps))
217
+ })()
218
+ }
219
+ return self
220
+ },
221
+
222
+ /**
223
+ * Stops and removes the Spinner.
224
+ */
225
+ stop: function() {
226
+ var el = this.el
227
+ if (el) {
228
+ clearTimeout(this.timeout)
229
+ if (el.parentNode) el.parentNode.removeChild(el)
230
+ this.el = undefined
231
+ }
232
+ return this
233
+ },
234
+
235
+ /**
236
+ * Internal method that draws the individual lines. Will be overwritten
237
+ * in VML fallback mode below.
238
+ */
239
+ lines: function(el, o) {
240
+ var i = 0
241
+ , start = (o.lines - 1) * (1 - o.direction) / 2
242
+ , seg
243
+
244
+ function fill(color, shadow) {
245
+ return css(createEl(), {
246
+ position: 'absolute',
247
+ width: (o.length+o.width) + 'px',
248
+ height: o.width + 'px',
249
+ background: color,
250
+ boxShadow: shadow,
251
+ transformOrigin: 'left',
252
+ transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
253
+ borderRadius: (o.corners * o.width>>1) + 'px'
254
+ })
255
+ }
256
+
257
+ for (; i < o.lines; i++) {
258
+ seg = css(createEl(), {
259
+ position: 'absolute',
260
+ top: 1+~(o.width/2) + 'px',
261
+ transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
262
+ opacity: o.opacity,
263
+ animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite'
264
+ })
265
+
266
+ if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}))
267
+ ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)')))
268
+ }
269
+ return el
270
+ },
271
+
272
+ /**
273
+ * Internal method that adjusts the opacity of a single line.
274
+ * Will be overwritten in VML fallback mode below.
275
+ */
276
+ opacity: function(el, i, val) {
277
+ if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
278
+ }
279
+
280
+ })
281
+
282
+
283
+ function initVML() {
284
+
285
+ /* Utility function to create a VML tag */
286
+ function vml(tag, attr) {
287
+ return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
288
+ }
289
+
290
+ // No CSS transforms but VML support, add a CSS rule for VML elements:
291
+ sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')
292
+
293
+ Spinner.prototype.lines = function(el, o) {
294
+ var r = o.length+o.width
295
+ , s = 2*r
296
+
297
+ function grp() {
298
+ return css(
299
+ vml('group', {
300
+ coordsize: s + ' ' + s,
301
+ coordorigin: -r + ' ' + -r
302
+ }),
303
+ { width: s, height: s }
304
+ )
305
+ }
306
+
307
+ var margin = -(o.width+o.length)*2 + 'px'
308
+ , g = css(grp(), {position: 'absolute', top: margin, left: margin})
309
+ , i
310
+
311
+ function seg(i, dx, filter) {
312
+ ins(g,
313
+ ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
314
+ ins(css(vml('roundrect', {arcsize: o.corners}), {
315
+ width: r,
316
+ height: o.width,
317
+ left: o.radius,
318
+ top: -o.width>>1,
319
+ filter: filter
320
+ }),
321
+ vml('fill', {color: getColor(o.color, i), opacity: o.opacity}),
322
+ vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
323
+ )
324
+ )
325
+ )
326
+ }
327
+
328
+ if (o.shadow)
329
+ for (i = 1; i <= o.lines; i++)
330
+ seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)')
331
+
332
+ for (i = 1; i <= o.lines; i++) seg(i)
333
+ return ins(el, g)
334
+ }
335
+
336
+ Spinner.prototype.opacity = function(el, i, val, o) {
337
+ var c = el.firstChild
338
+ o = o.shadow && o.lines || 0
339
+ if (c && i+o < c.childNodes.length) {
340
+ c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild
341
+ if (c) c.opacity = val
342
+ }
343
+ }
344
+ }
345
+
346
+ var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})
347
+
348
+ if (!vendor(probe, 'transform') && probe.adj) initVML()
349
+ else useCssAnimations = vendor(probe, 'animation')
350
+
351
+ return Spinner
352
+
353
+ }));
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brightcontent-attachments
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.33
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Developers at Brightin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-07 00:00:00.000000000 Z
11
+ date: 2014-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: brightcontent-core
@@ -16,110 +16,110 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.33
19
+ version: 2.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 2.0.33
26
+ version: 2.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: paperclip
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 3.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 3.0.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: jquery-fileupload-rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: sqlite3
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec-rails
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: capybara
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: launchy
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: factory_girl_rails
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  description: Separate attachment resource for brightcontent
@@ -128,26 +128,30 @@ executables: []
128
128
  extensions: []
129
129
  extra_rdoc_files: []
130
130
  files:
131
- - .gitignore
131
+ - ".gitignore"
132
132
  - Gemfile
133
133
  - README.md
134
134
  - Rakefile
135
135
  - app/assets/javascripts/brightcontent/.gitkeep
136
- - app/assets/javascripts/brightcontent/attachments.js
136
+ - app/assets/javascripts/brightcontent/attachments.js.coffee
137
+ - app/assets/stylesheets/brightcontent/attachments.css.scss
137
138
  - app/controllers/brightcontent/attachments_controller.rb
138
- - app/helpers/brightcontent/attachments_helper.rb
139
139
  - app/models/brightcontent/attachment.rb
140
140
  - app/views/brightcontent/attachments/_attachment.html.erb
141
141
  - app/views/brightcontent/attachments/show.html.erb
142
142
  - app/views/brightcontent/base/_form_field_attachments.html.erb
143
+ - app/views/brightcontent/base/_list_field_attachments.html.erb
143
144
  - brightcontent-attachments.gemspec
145
+ - config/locales/brightcontent_attachements.en.yml
146
+ - config/locales/brightcontent_attachements.nl.yml
144
147
  - config/routes.rb
145
148
  - db/migrate/20121222172513_create_attachments.rb
149
+ - db/migrate/20140203140819_add_position_to_attachments.rb
146
150
  - lib/brightcontent-attachments.rb
147
- - lib/brightcontent/attachable.rb
148
- - lib/brightcontent/attachment_model_extensions.rb
149
151
  - lib/brightcontent/attachments.rb
152
+ - lib/brightcontent/attachments/attachable.rb
150
153
  - lib/brightcontent/attachments/engine.rb
154
+ - lib/brightcontent/attachments/model_extensions.rb
151
155
  - lib/generators/brightcontent/attachments/install_generator.rb
152
156
  - script/rails
153
157
  - spec/dummy/README.rdoc
@@ -208,6 +212,7 @@ files:
208
212
  - spec/models/brightcontent/attachment_spec.rb
209
213
  - spec/spec_helper.rb
210
214
  - spec/support/acceptance_helper.rb
215
+ - vendor/assets/javascripts/spin.js
211
216
  homepage: http://brightin.nl
212
217
  licenses: []
213
218
  metadata: {}
@@ -217,17 +222,17 @@ require_paths:
217
222
  - lib
218
223
  required_ruby_version: !ruby/object:Gem::Requirement
219
224
  requirements:
220
- - - '>='
225
+ - - ">="
221
226
  - !ruby/object:Gem::Version
222
227
  version: '0'
223
228
  required_rubygems_version: !ruby/object:Gem::Requirement
224
229
  requirements:
225
- - - '>='
230
+ - - ">="
226
231
  - !ruby/object:Gem::Version
227
232
  version: '0'
228
233
  requirements: []
229
234
  rubyforge_project:
230
- rubygems_version: 2.0.2
235
+ rubygems_version: 2.2.2
231
236
  signing_key:
232
237
  specification_version: 4
233
238
  summary: Assets resource for brightcontent
@@ -1,14 +0,0 @@
1
- //= require jquery-fileupload/basic
2
-
3
- $(function () {
4
-
5
- var request_url = $("#attachable_url").val();
6
-
7
- $('#fileupload').fileupload({
8
- done: function (e, data) {
9
- $.get(request_url, function(data) {
10
- $('#attachments').html(data);
11
- });
12
- }
13
- });
14
- });
@@ -1,4 +0,0 @@
1
- module Brightcontent
2
- module AttachmentsHelper
3
- end
4
- end
@@ -1,15 +0,0 @@
1
- module Brightcontent
2
- module Attachable
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- add_brightcontent_column :attachments
7
- has_many :attachments, as: :attachable, dependent: :destroy, class_name: Brightcontent::Attachment, :inverse_of => :attachable
8
- end
9
-
10
- def attachment
11
- attachments.first
12
- end
13
-
14
- end
15
- end
@@ -1,13 +0,0 @@
1
- module Brightcontent
2
- module AttachmentModelExtensions
3
- extend ActiveSupport::Concern
4
-
5
- module ClassMethods
6
- attr_reader :attachment_styles
7
- def has_attached_files(styles)
8
- include Brightcontent::Attachable
9
- @attachment_styles = styles
10
- end
11
- end
12
- end
13
- end