attachy 0.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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/LICENSE +21 -0
  4. data/README.md +108 -0
  5. data/lib/assets/javascripts/attachy.js +289 -0
  6. data/lib/attachy.rb +13 -0
  7. data/lib/attachy/builders/attachy/form_builder.rb +15 -0
  8. data/lib/attachy/engine.rb +16 -0
  9. data/lib/attachy/helpers/attachy/view_helper.rb +31 -0
  10. data/lib/attachy/models/attachy/extension.rb +79 -0
  11. data/lib/attachy/models/attachy/file.rb +59 -0
  12. data/lib/attachy/models/attachy/viewer.rb +170 -0
  13. data/lib/attachy/version.rb +3 -0
  14. data/lib/generators/attachy/install_generator.rb +25 -0
  15. data/lib/generators/attachy/templates/config/attachy.yml.erb +15 -0
  16. data/lib/generators/attachy/templates/db/migrate/create_attachy_files_table.rb +19 -0
  17. data/lib/generators/attachy/templates/public/cloudinary_cors.html +46 -0
  18. data/spec/builders/attachy/form_builder/attachy_content_spec.rb +35 -0
  19. data/spec/builders/attachy/form_builder/attachy_file_field_spec.rb +23 -0
  20. data/spec/builders/attachy/form_builder/attachy_spec.rb +35 -0
  21. data/spec/factories/attachy/file.rb +12 -0
  22. data/spec/factories/user.rb +5 -0
  23. data/spec/helpers/attachy/attachy_content_spec.rb +21 -0
  24. data/spec/helpers/attachy/attachy_file_field_spec.rb +21 -0
  25. data/spec/helpers/attachy/attachy_spec.rb +35 -0
  26. data/spec/models/attachy/callback/destroy_file_spec.rb +55 -0
  27. data/spec/models/attachy/callback/remove_tmp_tag_spec.rb +11 -0
  28. data/spec/models/attachy/extension/user/avatar_spec.rb +91 -0
  29. data/spec/models/attachy/extension/user/photos_spec.rb +88 -0
  30. data/spec/models/attachy/file/config_spec.rb +11 -0
  31. data/spec/models/attachy/file/default_spec.rb +26 -0
  32. data/spec/models/attachy/file/path_spec.rb +16 -0
  33. data/spec/models/attachy/file/transform_spec.rb +86 -0
  34. data/spec/models/attachy/file_spec.rb +14 -0
  35. data/spec/models/attachy/viewer/attachments_spec.rb +28 -0
  36. data/spec/models/attachy/viewer/button_label_options_spec.rb +15 -0
  37. data/spec/models/attachy/viewer/button_label_spec.rb +34 -0
  38. data/spec/models/attachy/viewer/content_options_spec.rb +29 -0
  39. data/spec/models/attachy/viewer/content_spec.rb +62 -0
  40. data/spec/models/attachy/viewer/field_options_spec.rb +18 -0
  41. data/spec/models/attachy/viewer/field_spec.rb +56 -0
  42. data/spec/models/attachy/viewer/file_button_options_spec.rb +18 -0
  43. data/spec/models/attachy/viewer/file_button_spec.rb +57 -0
  44. data/spec/models/attachy/viewer/file_field_options_spec.rb +90 -0
  45. data/spec/models/attachy/viewer/file_field_spec.rb +25 -0
  46. data/spec/models/attachy/viewer/hidden_field_spec.rb +22 -0
  47. data/spec/models/attachy/viewer/image_spec.rb +170 -0
  48. data/spec/models/attachy/viewer/link_options_spec.rb +18 -0
  49. data/spec/models/attachy/viewer/link_spec.rb +131 -0
  50. data/spec/models/attachy/viewer/node_options_spec.rb +18 -0
  51. data/spec/models/attachy/viewer/node_spec.rb +134 -0
  52. data/spec/models/attachy/viewer/nodes_spec.rb +21 -0
  53. data/spec/models/attachy/viewer/remove_button_options_spec.rb +18 -0
  54. data/spec/models/attachy/viewer/transform_spec.rb +44 -0
  55. data/spec/models/attachy/viewer/value_spec.rb +83 -0
  56. data/spec/models/user_spec.rb +9 -0
  57. data/spec/rails_helper.rb +11 -0
  58. data/spec/support/common.rb +20 -0
  59. data/spec/support/database_cleaner.rb +19 -0
  60. data/spec/support/db/migrate/create_users_table.rb +7 -0
  61. data/spec/support/factory_girl.rb +7 -0
  62. data/spec/support/html_matchers.rb +5 -0
  63. data/spec/support/migrate.rb +4 -0
  64. data/spec/support/models/user.rb +5 -0
  65. data/spec/support/shoulda.rb +8 -0
  66. metadata +365 -0
@@ -0,0 +1,11 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::File, '#config' do
4
+ before do
5
+ allow(Rails.application).to receive(:config_for).with(:attachy) { :config }
6
+ end
7
+
8
+ it 'returns the config data' do
9
+ expect(described_class.config).to eq :config
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::File, '#default' do
4
+ before do
5
+ allow(::Rails).to receive_message_chain(:application, :config_for).with(:attachy) do
6
+ {
7
+ 'default' => {
8
+ 'image' => {
9
+ 'public_id' => 'default',
10
+ 'format' => 'png',
11
+ 'version' => 1
12
+ }
13
+ }
14
+ }
15
+ end
16
+ end
17
+
18
+ it 'returns a new file object with the config values' do
19
+ default = described_class.default
20
+
21
+ expect(default).to be_new_record
22
+ expect(default.format).to eq 'png'
23
+ expect(default.public_id).to eq 'default'
24
+ expect(default.version).to eq '1'
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::File, '.url' do
4
+ let!(:file) { described_class.new public_id: :public_id }
5
+ let!(:options) { { key: :value } }
6
+
7
+ before do
8
+ allow(file).to receive(:transform).with(options) { :transform }
9
+ end
10
+
11
+ it 'returns a cloudinary url' do
12
+ expect(Cloudinary::Utils).to receive(:cloudinary_url).with('public_id', :transform) { :url }
13
+
14
+ expect(file.url(key: :value)).to eq :url
15
+ end
16
+ end
@@ -0,0 +1,86 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::File, '.transform' do
4
+ context 'when crop is :none' do
5
+ let!(:file) { build :file }
6
+
7
+ it 'removes :crop, :height and :width' do
8
+ expect(file.transform(crop: :none, key: :value)).to eq(
9
+ format: file.format,
10
+ key: :value,
11
+ public_id: file.public_id,
12
+ secure: true,
13
+ sign_url: true,
14
+ version: file.version
15
+ )
16
+ end
17
+ end
18
+
19
+ context 'when crop is not :none' do
20
+ describe ':crop' do
21
+ context 'when not given' do
22
+ specify { expect(subject.transform[:crop]).to eq :fill }
23
+ end
24
+
25
+ context 'with given' do
26
+ specify { expect(subject.transform(crop: :scale)[:crop]).to eq :scale }
27
+ end
28
+ end
29
+
30
+ describe ':format' do
31
+ context 'when not given' do
32
+ let!(:file) { described_class.new format: :png }
33
+
34
+ it 'uses the file one' do
35
+ expect(file.transform[:format]).to eq 'png'
36
+ end
37
+ end
38
+
39
+ context 'when given' do
40
+ let!(:file) { described_class.new format: :png }
41
+
42
+ it 'uses the file one' do
43
+ expect(file.transform(format: :gif)[:format]).to eq :gif
44
+ end
45
+ end
46
+ end
47
+
48
+ describe ':secure' do
49
+ context 'when not given' do
50
+ specify { expect(subject.transform[:secure]).to eq true }
51
+ end
52
+
53
+ context 'when not given' do
54
+ specify { expect(subject.transform(secure: false)[:secure]).to eq false }
55
+ end
56
+ end
57
+
58
+ describe ':sign_url' do
59
+ context 'when given' do
60
+ specify { expect(subject.transform[:sign_url]).to eq true }
61
+ end
62
+
63
+ context 'when not given' do
64
+ specify { expect(subject.transform(sign_url: false)[:sign_url]).to eq false }
65
+ end
66
+ end
67
+
68
+ describe ':version' do
69
+ context 'when not given' do
70
+ let!(:file) { described_class.new version: 42 }
71
+
72
+ it 'uses the file one' do
73
+ expect(file.transform[:version]).to eq '42'
74
+ end
75
+ end
76
+
77
+ context 'when given' do
78
+ let!(:file) { described_class.new version: 42 }
79
+
80
+ it 'uses the file one' do
81
+ expect(file.transform(version: 7)[:version]).to eq 7
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::File do
4
+ it { expect(build(:file)).to be_valid }
5
+
6
+ it { is_expected.to belong_to :attachable }
7
+
8
+ it { is_expected.to validate_presence_of :format }
9
+ it { is_expected.to validate_presence_of :height }
10
+ it { is_expected.to validate_presence_of :public_id }
11
+ it { is_expected.to validate_presence_of :resource_type }
12
+ it { is_expected.to validate_presence_of :scope }
13
+ it { is_expected.to validate_presence_of :version }
14
+ end
@@ -0,0 +1,28 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.attachments' do
4
+ let!(:object) { create :user }
5
+
6
+ before { allow(Cloudinary::Uploader).to receive(:remove_tag) }
7
+
8
+ subject { described_class.new method, object }
9
+
10
+ context 'with one file' do
11
+ let!(:method) { :avatar }
12
+ let!(:file) { create :file, attachable: object, scope: method }
13
+
14
+ it 'returns an array' do
15
+ expect(subject.attachments).to eq [file]
16
+ end
17
+ end
18
+
19
+ context 'with more than one files' do
20
+ let!(:method) { :photos }
21
+ let!(:file_1) { create :file, attachable: object, scope: method }
22
+ let!(:file_2) { create :file, attachable: object, scope: method }
23
+
24
+ it 'returns an array' do
25
+ expect(subject.attachments).to eq [file_1, file_2]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.button_label_options' do
4
+ let!(:object) { create :user }
5
+ let!(:method) { :avatar }
6
+ let(:file) { create :file, attachable: object, scope: method }
7
+
8
+ before { allow(Cloudinary::Uploader).to receive(:remove_tag) }
9
+
10
+ subject { described_class.new method, object }
11
+
12
+ it 'returns the default button label options' do
13
+ expect(subject.button_label_options).to eq(text: '...')
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.button_label' do
4
+ let!(:method) { :avatar }
5
+ let!(:object) { create :user }
6
+ let(:file) { create :file, attachable: object }
7
+ let!(:options) { { button: { html: { key: :value } } } }
8
+
9
+ before { allow(Cloudinary::Uploader).to receive(:remove_tag) }
10
+
11
+ subject { described_class.new method, object, options }
12
+
13
+ describe 'default options' do
14
+ it 'uses generic button options' do
15
+ el = subject.button_label
16
+
17
+ expect(el).to have_tag :span, with: { key: 'value' } do
18
+ with_text '...'
19
+ end
20
+ end
21
+ end
22
+
23
+ context 'when :html is present' do
24
+ let!(:html) { { key: 2, text: '---' } }
25
+
26
+ it 'merges with default' do
27
+ el = subject.button_label(html: html)
28
+
29
+ expect(el).to have_tag :span, with: { key: '2' } do
30
+ with_text '---'
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,29 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.content_options' do
4
+ let!(:object) { create :user }
5
+ let!(:method) { :avatar }
6
+ let(:file) { create :file, attachable: object, scope: method }
7
+ let!(:options) { { t: { height: 600, width: 800 } } }
8
+
9
+ before do
10
+ allow(Cloudinary::Uploader).to receive(:remove_tag)
11
+
12
+ allow(subject).to receive(:metadata) { { crop: :crop, multiple: :multiple } }
13
+ end
14
+
15
+ subject { described_class.new method, object, options }
16
+
17
+ it 'returns the default field options' do
18
+ expect(subject.content_options).to eq(
19
+ class: :attachy__content,
20
+
21
+ data: {
22
+ crop: :crop,
23
+ height: 600,
24
+ multiple: :multiple,
25
+ width: 800
26
+ }
27
+ )
28
+ end
29
+ end
@@ -0,0 +1,62 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.content' do
4
+ let!(:method) { :avatar }
5
+ let!(:object) { create :user }
6
+ let!(:options) { { button: { html: { key: :value } } } }
7
+
8
+ let!(:file) do
9
+ allow(Cloudinary::Uploader).to receive(:remove_tag)
10
+
11
+ create :file, attachable: object
12
+ end
13
+
14
+ before do
15
+ nodes = double
16
+ join = double
17
+
18
+ allow(subject).to receive(:nodes) { nodes }
19
+ allow(nodes).to receive(:join) { join }
20
+ allow(join).to receive(:html_safe) { :safe }
21
+
22
+ allow(subject).to receive(:content_options) { { class: :attachy__content } }
23
+ end
24
+
25
+ subject { described_class.new method, object, options }
26
+
27
+ describe 'default options' do
28
+ it 'uses generic button options' do
29
+ el = subject.content
30
+
31
+ expect(el).to have_tag :ul, with: { class: 'attachy__content' }
32
+ end
33
+
34
+ it 'builds a content based on nodes' do
35
+ el = subject.content
36
+
37
+ expect(el).to have_tag :ul do
38
+ with_text 'safe'
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'when :html is present' do
44
+ let!(:html) { { key: :value } }
45
+
46
+ it 'merges with default' do
47
+ el = subject.content(html: html)
48
+
49
+ expect(el).to have_tag :ul, with: { class: 'attachy__content', key: 'value' }
50
+ end
51
+ end
52
+
53
+ context 'when a block is given' do
54
+ let!(:html) { { key: :value } }
55
+
56
+ it 'yields the :html options' do
57
+ subject.content(html: html) do |htm|
58
+ expect(htm).to eq(key: :value, class: :attachy__content)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.field_options' do
4
+ let!(:object) { create :user }
5
+ let!(:method) { :avatar }
6
+
7
+ let!(:file) do
8
+ allow(Cloudinary::Uploader).to receive(:remove_tag)
9
+
10
+ create :file, attachable: object, scope: method
11
+ end
12
+
13
+ subject { described_class.new method, object }
14
+
15
+ it 'returns the default field options' do
16
+ expect(subject.field_options).to eq(class: :attachy)
17
+ end
18
+ end
@@ -0,0 +1,56 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.field' do
4
+ let!(:method) { :avatar }
5
+ let!(:object) { create :user }
6
+ let!(:options) { { button: { html: { key: :value } } } }
7
+
8
+ let!(:file) do
9
+ allow(Cloudinary::Uploader).to receive(:remove_tag)
10
+
11
+ create :file, attachable: object
12
+ end
13
+
14
+ before do
15
+ allow(subject).to receive(:content) { '1' }
16
+ allow(subject).to receive(:file_button) { '2' }
17
+ end
18
+
19
+ subject { described_class.new method, object, options }
20
+
21
+ describe 'default options' do
22
+ it 'uses generic button options' do
23
+ el = subject.field
24
+
25
+ expect(el).to have_tag :div, with: { class: 'attachy' }
26
+ end
27
+
28
+ it 'builds a content based on content and file field' do
29
+ el = subject.field
30
+
31
+ expect(el).to have_tag :div do
32
+ with_text '12'
33
+ end
34
+ end
35
+ end
36
+
37
+ context 'when :html is present' do
38
+ let!(:html) { { key: :value } }
39
+
40
+ it 'merges with default' do
41
+ el = subject.field(html: html)
42
+
43
+ expect(el).to have_tag :div, with: { class: 'attachy', key: 'value' }
44
+ end
45
+ end
46
+
47
+ context 'when a block is given' do
48
+ let!(:html) { { key: :value } }
49
+
50
+ it 'yields the :html options' do
51
+ subject.field(html: html) do |htm|
52
+ expect(htm).to eq(key: :value, class: :attachy)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.file_button_options' do
4
+ let!(:object) { create :user }
5
+ let!(:method) { :avatar }
6
+
7
+ let!(:file) do
8
+ allow(Cloudinary::Uploader).to receive(:remove_tag)
9
+
10
+ create :file, attachable: object, scope: method
11
+ end
12
+
13
+ subject { described_class.new method, object }
14
+
15
+ it 'returns the default file button options' do
16
+ expect(subject.file_button_options).to eq(class: :attachy__button)
17
+ end
18
+ end
@@ -0,0 +1,57 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Attachy::Viewer, '.file_button' do
4
+ let!(:method) { :avatar }
5
+ let!(:object) { create :user }
6
+ let!(:options) { { button: { html: { key: :value } } } }
7
+
8
+ let!(:file) do
9
+ allow(Cloudinary::Uploader).to receive(:remove_tag)
10
+
11
+ create :file, attachable: object
12
+ end
13
+
14
+ subject { described_class.new method, object, options }
15
+
16
+ before do
17
+ allow(subject).to receive(:button_label) { '1' }
18
+ allow(subject).to receive(:file_field) { '2' }
19
+ allow(subject).to receive(:hidden_field) { '3' }
20
+ end
21
+
22
+ describe 'default options' do
23
+ it 'uses generic button options' do
24
+ el = subject.file_button
25
+
26
+ expect(el).to have_tag :div, with: { class: 'attachy__button', key: :value }
27
+ end
28
+
29
+ it 'builds a content based on button label, file field and hidden field' do
30
+ el = subject.file_button
31
+
32
+ expect(el).to have_tag :div do
33
+ with_text '123'
34
+ end
35
+ end
36
+ end
37
+
38
+ context 'when :html is present' do
39
+ let!(:html) { { key: :value } }
40
+
41
+ it 'merges with default' do
42
+ el = subject.file_button
43
+
44
+ expect(el).to have_tag :div, with: { class: 'attachy__button', key: :value }
45
+ end
46
+ end
47
+
48
+ context 'when a block is given' do
49
+ let!(:html) { { key: :value } }
50
+
51
+ it 'yields the :html options' do
52
+ subject.file_button(html: html) do |htm|
53
+ expect(htm).to eq(key: :value, class: :attachy__button)
54
+ end
55
+ end
56
+ end
57
+ end