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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE +21 -0
- data/README.md +108 -0
- data/lib/assets/javascripts/attachy.js +289 -0
- data/lib/attachy.rb +13 -0
- data/lib/attachy/builders/attachy/form_builder.rb +15 -0
- data/lib/attachy/engine.rb +16 -0
- data/lib/attachy/helpers/attachy/view_helper.rb +31 -0
- data/lib/attachy/models/attachy/extension.rb +79 -0
- data/lib/attachy/models/attachy/file.rb +59 -0
- data/lib/attachy/models/attachy/viewer.rb +170 -0
- data/lib/attachy/version.rb +3 -0
- data/lib/generators/attachy/install_generator.rb +25 -0
- data/lib/generators/attachy/templates/config/attachy.yml.erb +15 -0
- data/lib/generators/attachy/templates/db/migrate/create_attachy_files_table.rb +19 -0
- data/lib/generators/attachy/templates/public/cloudinary_cors.html +46 -0
- data/spec/builders/attachy/form_builder/attachy_content_spec.rb +35 -0
- data/spec/builders/attachy/form_builder/attachy_file_field_spec.rb +23 -0
- data/spec/builders/attachy/form_builder/attachy_spec.rb +35 -0
- data/spec/factories/attachy/file.rb +12 -0
- data/spec/factories/user.rb +5 -0
- data/spec/helpers/attachy/attachy_content_spec.rb +21 -0
- data/spec/helpers/attachy/attachy_file_field_spec.rb +21 -0
- data/spec/helpers/attachy/attachy_spec.rb +35 -0
- data/spec/models/attachy/callback/destroy_file_spec.rb +55 -0
- data/spec/models/attachy/callback/remove_tmp_tag_spec.rb +11 -0
- data/spec/models/attachy/extension/user/avatar_spec.rb +91 -0
- data/spec/models/attachy/extension/user/photos_spec.rb +88 -0
- data/spec/models/attachy/file/config_spec.rb +11 -0
- data/spec/models/attachy/file/default_spec.rb +26 -0
- data/spec/models/attachy/file/path_spec.rb +16 -0
- data/spec/models/attachy/file/transform_spec.rb +86 -0
- data/spec/models/attachy/file_spec.rb +14 -0
- data/spec/models/attachy/viewer/attachments_spec.rb +28 -0
- data/spec/models/attachy/viewer/button_label_options_spec.rb +15 -0
- data/spec/models/attachy/viewer/button_label_spec.rb +34 -0
- data/spec/models/attachy/viewer/content_options_spec.rb +29 -0
- data/spec/models/attachy/viewer/content_spec.rb +62 -0
- data/spec/models/attachy/viewer/field_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/field_spec.rb +56 -0
- data/spec/models/attachy/viewer/file_button_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/file_button_spec.rb +57 -0
- data/spec/models/attachy/viewer/file_field_options_spec.rb +90 -0
- data/spec/models/attachy/viewer/file_field_spec.rb +25 -0
- data/spec/models/attachy/viewer/hidden_field_spec.rb +22 -0
- data/spec/models/attachy/viewer/image_spec.rb +170 -0
- data/spec/models/attachy/viewer/link_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/link_spec.rb +131 -0
- data/spec/models/attachy/viewer/node_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/node_spec.rb +134 -0
- data/spec/models/attachy/viewer/nodes_spec.rb +21 -0
- data/spec/models/attachy/viewer/remove_button_options_spec.rb +18 -0
- data/spec/models/attachy/viewer/transform_spec.rb +44 -0
- data/spec/models/attachy/viewer/value_spec.rb +83 -0
- data/spec/models/user_spec.rb +9 -0
- data/spec/rails_helper.rb +11 -0
- data/spec/support/common.rb +20 -0
- data/spec/support/database_cleaner.rb +19 -0
- data/spec/support/db/migrate/create_users_table.rb +7 -0
- data/spec/support/factory_girl.rb +7 -0
- data/spec/support/html_matchers.rb +5 -0
- data/spec/support/migrate.rb +4 -0
- data/spec/support/models/user.rb +5 -0
- data/spec/support/shoulda.rb +8 -0
- metadata +365 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!DOCTYPE HTML>
|
|
2
|
+
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<script>
|
|
9
|
+
/*
|
|
10
|
+
json2.js
|
|
11
|
+
2016-10-28
|
|
12
|
+
|
|
13
|
+
Public Domain.
|
|
14
|
+
|
|
15
|
+
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
16
|
+
|
|
17
|
+
See http://www.JSON.org/js.html
|
|
18
|
+
This code should be minified before deployment.
|
|
19
|
+
|
|
20
|
+
See http://javascript.crockford.com/jsmin.html
|
|
21
|
+
|
|
22
|
+
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
|
23
|
+
NOT CONTROL.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
"object"!=typeof JSON&&(JSON={}),function(){"use strict";function f(a){return a<10?"0"+a:a}function this_value(){return this.valueOf()}function quote(a){return rx_escapable.lastIndex=0,rx_escapable.test(a)?'"'+a.replace(rx_escapable,function(a){var b=meta[a];return"string"==typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function str(a,b){var c,d,e,f,h,g=gap,i=b[a];switch(i&&"object"==typeof i&&"function"==typeof i.toJSON&&(i=i.toJSON(a)),"function"==typeof rep&&(i=rep.call(b,a,i)),typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";if(gap+=indent,h=[],"[object Array]"===Object.prototype.toString.apply(i)){for(f=i.length,c=0;c<f;c+=1)h[c]=str(c,i)||"null";return e=0===h.length?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g,e}if(rep&&"object"==typeof rep)for(f=rep.length,c=0;c<f;c+=1)"string"==typeof rep[c]&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));return e=0===h.length?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g,e}}var rx_one=/^[\],:{}\s]*$/,rx_two=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,rx_three=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,rx_four=/(?:^|:|,)(?:\s*\[)+/g,rx_escapable=/[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,rx_dangerous=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},Boolean.prototype.toJSON=this_value,Number.prototype.toJSON=this_value,String.prototype.toJSON=this_value);var gap,indent,meta,rep;"function"!=typeof JSON.stringify&&(meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(a,b,c){var d;if(gap="",indent="","number"==typeof c)for(d=0;d<c;d+=1)indent+=" ";else"string"==typeof c&&(indent=c);if(rep=b,b&&"function"!=typeof b&&("object"!=typeof b||"number"!=typeof b.length))throw new Error("JSON.stringify");return str("",{"":a})}),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&"object"==typeof e)for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),void 0!==d?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;if(text=String(text),rx_dangerous.lastIndex=0,rx_dangerous.test(text)&&(text=text.replace(rx_dangerous,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})),rx_one.test(text.replace(rx_two,"@").replace(rx_three,"]").replace(rx_four,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}();
|
|
27
|
+
/* end of json2.js */
|
|
28
|
+
|
|
29
|
+
function parse(query) {
|
|
30
|
+
var
|
|
31
|
+
result = {},
|
|
32
|
+
params = query.split('&');
|
|
33
|
+
|
|
34
|
+
for (var i = 0; i < params.length; i++) {
|
|
35
|
+
var param = params[i].split('=');
|
|
36
|
+
|
|
37
|
+
result[param[0]] = decodeURIComponent(param[1]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return JSON.stringify(result);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
document.body.textContent = document.body.innerText = parse(window.location.search.slice(1));
|
|
44
|
+
</script>
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class Dummy < ActionView::Helpers::FormBuilder
|
|
4
|
+
include Attachy::FormBuilder
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class DummyHelper
|
|
8
|
+
include Attachy::ViewHelper
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
RSpec.describe Dummy, '.attachy_content' do
|
|
12
|
+
let!(:method) { :avatar }
|
|
13
|
+
let!(:options) { { key: :value } }
|
|
14
|
+
let!(:object) { create :user }
|
|
15
|
+
let!(:template) { DummyHelper.new }
|
|
16
|
+
let!(:dummy) { described_class.new method, object, template, options }
|
|
17
|
+
|
|
18
|
+
context 'with no block' do
|
|
19
|
+
xit 'delegates to view helper' do
|
|
20
|
+
expect(template).to receive(:attachy_content).with(method, object, options, nil)
|
|
21
|
+
|
|
22
|
+
dummy.attachy_content method, options
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'with block' do
|
|
27
|
+
let!(:block) { proc {} }
|
|
28
|
+
|
|
29
|
+
xit 'delegates to view helper with block' do
|
|
30
|
+
expect(template).to receive(:attachy_content).with(method, object, options, block)
|
|
31
|
+
|
|
32
|
+
dummy.attachy_content method, options, &block
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class Dummy < ActionView::Helpers::FormBuilder
|
|
4
|
+
include Attachy::FormBuilder
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class DummyHelper
|
|
8
|
+
include Attachy::ViewHelper
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
RSpec.describe Dummy, '.attachy_file_field' do
|
|
12
|
+
let!(:method) { :avatar }
|
|
13
|
+
let!(:options) { { key: :value } }
|
|
14
|
+
let!(:object) { create :user }
|
|
15
|
+
let!(:template) { DummyHelper.new }
|
|
16
|
+
let!(:dummy) { described_class.new method, object, template, options }
|
|
17
|
+
|
|
18
|
+
it 'delegates to view helper' do
|
|
19
|
+
expect(template).to receive(:attachy_file_field).with(method, object, options)
|
|
20
|
+
|
|
21
|
+
dummy.attachy_file_field method, options
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class Dummy < ActionView::Helpers::FormBuilder
|
|
4
|
+
include Attachy::FormBuilder
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class DummyHelper
|
|
8
|
+
include Attachy::ViewHelper
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
RSpec.describe Dummy, '.attachy' do
|
|
12
|
+
let!(:method) { :avatar }
|
|
13
|
+
let!(:options) { { key: :value } }
|
|
14
|
+
let!(:object) { create :user }
|
|
15
|
+
let!(:template) { DummyHelper.new }
|
|
16
|
+
let!(:dummy) { described_class.new method, object, template, options }
|
|
17
|
+
|
|
18
|
+
context 'with no block' do
|
|
19
|
+
it 'delegates to view helper' do
|
|
20
|
+
expect(template).to receive(:attachy).with(method, object, options, nil)
|
|
21
|
+
|
|
22
|
+
dummy.attachy method, options
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'with block' do
|
|
27
|
+
let!(:block) { proc {} }
|
|
28
|
+
|
|
29
|
+
it 'delegates to view helper with block' do
|
|
30
|
+
expect(template).to receive(:attachy).with(method, object, options, block)
|
|
31
|
+
|
|
32
|
+
dummy.attachy method, options, &block
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class DummyHelper
|
|
4
|
+
include Attachy::ViewHelper
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
RSpec.describe DummyHelper, '.attachy_content' do
|
|
8
|
+
let!(:method) { :avatar }
|
|
9
|
+
let!(:options) { { key: :value } }
|
|
10
|
+
let!(:object) { create :user }
|
|
11
|
+
let!(:helper) { DummyHelper.new }
|
|
12
|
+
let!(:viewer) { double Attachy::Viewer, content: :content }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
allow(Attachy::Viewer).to receive(:new).with(method, object, options, helper) { viewer }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'calls content from viewer' do
|
|
19
|
+
expect(helper.attachy_content(method, object, options)).to eq :content
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class DummyHelper
|
|
4
|
+
include Attachy::ViewHelper
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
RSpec.describe DummyHelper, '.attachy_file_field' do
|
|
8
|
+
let!(:method) { :avatar }
|
|
9
|
+
let!(:options) { { key: :value } }
|
|
10
|
+
let!(:object) { create :user }
|
|
11
|
+
let!(:helper) { DummyHelper.new }
|
|
12
|
+
let!(:viewer) { double Attachy::Viewer, file_field: :file_field }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
allow(Attachy::Viewer).to receive(:new).with(method, object, options, helper) { viewer }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'calls file_field from viewer' do
|
|
19
|
+
expect(helper.attachy_file_field(method, object, options)).to eq :file_field
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class DummyHelper
|
|
4
|
+
include Attachy::ViewHelper
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
RSpec.describe DummyHelper, '.attachy' do
|
|
8
|
+
let!(:method) { :avatar }
|
|
9
|
+
let!(:options) { { key: :value } }
|
|
10
|
+
let!(:object) { create :user }
|
|
11
|
+
let!(:helper) { DummyHelper.new }
|
|
12
|
+
let!(:viewer) { double Attachy::Viewer, field: :field }
|
|
13
|
+
|
|
14
|
+
context 'with no block' do
|
|
15
|
+
before do
|
|
16
|
+
allow(Attachy::Viewer).to receive(:new).with(method, object, options, helper) { viewer }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'calls field from viewer' do
|
|
20
|
+
expect(helper.attachy(method, object, options, nil)).to eq :field
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'with block' do
|
|
25
|
+
let!(:block) { proc { |v| expect(v.field).to eq :field } }
|
|
26
|
+
|
|
27
|
+
before do
|
|
28
|
+
allow(Attachy::Viewer).to receive(:new).with(method, object, options, helper) { viewer }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'delegates to view helper with block' do
|
|
32
|
+
helper.attachy method, object, options, block
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe User, ':destroy_file' do
|
|
4
|
+
let!(:user) { create :user }
|
|
5
|
+
|
|
6
|
+
let!(:photo) do
|
|
7
|
+
expect(Cloudinary::Uploader).to receive(:remove_tag)
|
|
8
|
+
|
|
9
|
+
create :file, public_id: 'public_id', scope: :photos, attachable: user
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context 'via assign' do
|
|
13
|
+
context 'via assign on relation' do
|
|
14
|
+
it 'removes the file via api' do
|
|
15
|
+
expect(Cloudinary::Uploader).to receive(:destroy).with('public_id')
|
|
16
|
+
|
|
17
|
+
user.photos_files = []
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context 'via assign on scope' do
|
|
22
|
+
it 'removes the file via api' do
|
|
23
|
+
expect(Cloudinary::Uploader).to receive(:destroy).with('public_id')
|
|
24
|
+
|
|
25
|
+
user.photos = '[]'
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'via method' do
|
|
31
|
+
context 'via method over one record' do
|
|
32
|
+
it 'removes the file via api' do
|
|
33
|
+
expect(Cloudinary::Uploader).to receive(:destroy).with('public_id')
|
|
34
|
+
|
|
35
|
+
user.photos_files.first.destroy
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'via method over criteria' do
|
|
40
|
+
it 'removes the file via api' do
|
|
41
|
+
expect(Cloudinary::Uploader).to receive(:destroy).with('public_id')
|
|
42
|
+
|
|
43
|
+
user.photos_files.destroy_all
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context 'via .clear' do
|
|
48
|
+
it 'does not removes the file via api' do
|
|
49
|
+
expect(Cloudinary::Uploader).not_to receive(:destroy)
|
|
50
|
+
|
|
51
|
+
user.photos_files.clear
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe User, ':remove_tmp_tag' do
|
|
4
|
+
let!(:user) { create :user }
|
|
5
|
+
|
|
6
|
+
it 'removes the tmp tag via api' do
|
|
7
|
+
expect(Cloudinary::Uploader).to receive(:remove_tag).with(Attachy::TMP_TAG, ['public_id'])
|
|
8
|
+
|
|
9
|
+
create :file, public_id: 'public_id', attachable: user
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe User, ':avatar' do
|
|
4
|
+
before do
|
|
5
|
+
allow(Cloudinary::Uploader).to receive(:remove_tag)
|
|
6
|
+
allow(Cloudinary::Uploader).to receive(:destroy)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe ':avatar_files' do
|
|
10
|
+
let!(:user) { create :user }
|
|
11
|
+
let!(:avatar_1) { create :file, scope: :avatar, attachable: user }
|
|
12
|
+
let!(:avatar_2) { create :file, scope: :avatar, attachable: user }
|
|
13
|
+
|
|
14
|
+
it 'returns all records even in the singular' do
|
|
15
|
+
expect(user.avatar_files).to match_array [avatar_1, avatar_2]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe ':avatar_files=' do
|
|
20
|
+
let!(:user) { create :user }
|
|
21
|
+
let!(:avatar_1) { create :file, scope: :avatar }
|
|
22
|
+
let!(:avatar_2) { create :file, scope: :avatar }
|
|
23
|
+
|
|
24
|
+
context 'when given records' do
|
|
25
|
+
before { user.avatar_files = [avatar_1, avatar_2] }
|
|
26
|
+
|
|
27
|
+
it 'is saved' do
|
|
28
|
+
expect(user.avatar_files).to match_array [avatar_1, avatar_2]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context 'when given no records' do
|
|
33
|
+
before { user.avatar_files = [avatar_1, avatar_2] }
|
|
34
|
+
|
|
35
|
+
it 'clears the existents' do
|
|
36
|
+
user.avatar_files = []
|
|
37
|
+
|
|
38
|
+
expect(user.avatar_files).to eq []
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe ':avatar' do
|
|
44
|
+
let!(:user) { create :user }
|
|
45
|
+
|
|
46
|
+
context 'with no file' do
|
|
47
|
+
before do
|
|
48
|
+
allow(Attachy::File).to receive(:default) { :default }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'returns a default file' do
|
|
52
|
+
expect(user.avatar).to eq :default
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'with file' do
|
|
57
|
+
let!(:avatar_1) { create :file, scope: :avatar, attachable: user }
|
|
58
|
+
let!(:avatar_2) { create :file, scope: :avatar, attachable: user }
|
|
59
|
+
|
|
60
|
+
it 'returns just the last one simulating a has_one' do
|
|
61
|
+
expect(user.avatar).to eq avatar_2
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe ':avatar?' do
|
|
67
|
+
let!(:user) { create :user }
|
|
68
|
+
|
|
69
|
+
context 'with no records' do
|
|
70
|
+
specify { expect(user.avatar?).to eq false }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'with records' do
|
|
74
|
+
before { create :file, scope: :avatar, attachable: user }
|
|
75
|
+
|
|
76
|
+
specify { expect(user.avatar?).to eq true }
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe ':avatar_metadata' do
|
|
81
|
+
let!(:user) { create :user }
|
|
82
|
+
|
|
83
|
+
it 'returns the metadata' do
|
|
84
|
+
expect(user.avatar_metadata).to eq(
|
|
85
|
+
accept: %i[jpg png],
|
|
86
|
+
multiple: false,
|
|
87
|
+
scope: :avatar
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe User, ':photos' do
|
|
4
|
+
before do
|
|
5
|
+
allow(Cloudinary::Uploader).to receive(:remove_tag)
|
|
6
|
+
allow(Cloudinary::Uploader).to receive(:destroy)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe ':photos_files' do
|
|
10
|
+
let!(:user) { create :user }
|
|
11
|
+
let!(:photo_1) { create :file, scope: :photos, attachable: user }
|
|
12
|
+
let!(:photo_2) { create :file, scope: :photos, attachable: user }
|
|
13
|
+
|
|
14
|
+
it 'returns all records' do
|
|
15
|
+
expect(user.photos_files).to match_array [photo_1, photo_2]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe ':photos_files=' do
|
|
20
|
+
let!(:user) { create :user }
|
|
21
|
+
let!(:photo_1) { create :file, scope: :photo }
|
|
22
|
+
let!(:photo_2) { create :file, scope: :photo }
|
|
23
|
+
|
|
24
|
+
context 'when given records' do
|
|
25
|
+
before { user.photos_files = [photo_1, photo_2] }
|
|
26
|
+
|
|
27
|
+
it 'is saved' do
|
|
28
|
+
expect(user.photos_files).to match_array [photo_1, photo_2]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context 'when given no records' do
|
|
33
|
+
before { user.photos_files = [photo_1, photo_2] }
|
|
34
|
+
|
|
35
|
+
it 'clears the existents' do
|
|
36
|
+
user.photos_files = []
|
|
37
|
+
|
|
38
|
+
expect(user.photos_files).to eq []
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe ':photo' do
|
|
44
|
+
let!(:user) { create :user }
|
|
45
|
+
|
|
46
|
+
context 'with no file' do
|
|
47
|
+
it 'returns empty' do
|
|
48
|
+
expect(user.photos).to eq []
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context 'with file' do
|
|
53
|
+
let!(:photo_1) { create :file, scope: :photos, attachable: user }
|
|
54
|
+
let!(:photo_2) { create :file, scope: :photos, attachable: user }
|
|
55
|
+
|
|
56
|
+
it 'returns all records' do
|
|
57
|
+
expect(user.photos).to match_array [photo_1, photo_2]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe ':photo?' do
|
|
63
|
+
let!(:user) { create :user }
|
|
64
|
+
|
|
65
|
+
context 'with no records' do
|
|
66
|
+
specify { expect(user.photos?).to eq false }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'with records' do
|
|
70
|
+
before { create :file, scope: :photos, attachable: user }
|
|
71
|
+
|
|
72
|
+
specify { expect(user.photos?).to eq true }
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe ':photos_metadata' do
|
|
77
|
+
let!(:user) { create :user }
|
|
78
|
+
|
|
79
|
+
it 'returns the metadata' do
|
|
80
|
+
expect(user.photos_metadata).to eq(
|
|
81
|
+
accept: %i[jpg png],
|
|
82
|
+
maximum: 10,
|
|
83
|
+
multiple: true,
|
|
84
|
+
scope: :photos
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|