carrierwave-neo4j 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/CHANGELOG.md +35 -0
- data/Gemfile +0 -2
- data/README.md +64 -4
- data/Rakefile +11 -0
- data/carrierwave-neo4j.gemspec +9 -7
- data/lib/carrierwave/neo4j.rb +177 -41
- data/lib/carrierwave/neo4j/uploader_converter.rb +16 -6
- data/lib/carrierwave/neo4j/version.rb +1 -1
- data/spec/fixtures/neo4j.png +0 -0
- data/spec/fixtures/ong.jpg +0 -0
- data/spec/helpers/database_cleaner.rb +29 -0
- data/spec/helpers/fake_book_migration.rb +13 -0
- data/spec/helpers/fake_migrations.rb +12 -0
- data/spec/helpers/fake_schema_migration.rb +13 -0
- data/spec/helpers/fake_user_migration.rb +13 -0
- data/spec/helpers/filesystem_cleaner.rb +12 -0
- data/spec/neo4j_realistic_spec.rb +104 -0
- data/spec/neo4j_sanity_spec.rb +137 -0
- data/spec/neo4j_spec.rb +148 -29
- data/spec/spec_helper.rb +23 -5
- metadata +91 -26
- data/spec/fixtures/tarja.jpg +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ee1ece089b8cbd55532f4c0cba7a7a19054b24edc86f81a077c5497c49f4c801
|
4
|
+
data.tar.gz: a8a1b8fb5355129bfb9fd41839b59bbeee38e5808d59cac0a21fcc7ee6291a55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2adb7d1d88b7f225d2d89c4bdcae75ada1f4fa3edfc5679cbd0aa034c80d6738bc2990dc9a2527555ae92837edbf9f447fb0ed811c9da133d2613c88019dd45
|
7
|
+
data.tar.gz: e9168769c2f8e656c3e8e1046e5c7d5fbaaec1d53269525557fe50b3f4a77ba08aa0966529cd5835750b4fe57b7b7a85b5e58aea3ac145b151f93e6c451b9a97
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
|
+
|
7
|
+
## [3.0.0] - 2020-07-15
|
8
|
+
|
9
|
+
### Fixed
|
10
|
+
|
11
|
+
- Updated and fixed all tests to work with neo4j.rb 9.x and CarrierWave 2.x
|
12
|
+
- Updated the overall format of the plugin to mirror CarrierWave::Orm::ActiveRecord as much as possible
|
13
|
+
- Files are now deleted correctly on `#destroy`
|
14
|
+
- File information is now correctly reloaded on `#find`
|
15
|
+
- Thanks @deobald for all the fixes.
|
16
|
+
|
17
|
+
## [2.0.4] - 2018-04-03
|
18
|
+
|
19
|
+
### Fixed
|
20
|
+
|
21
|
+
- Fix the fix from 2.0.3 (`@_mounters` is sometimes `nil`) (thanks @janbiedermann / see #15)
|
22
|
+
|
23
|
+
## [2.0.3] - 2018-04-01
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
|
27
|
+
- Make it work with recent Neo4j (thanks @janbiedermann / see #14)
|
28
|
+
|
29
|
+
## [2.0.2]
|
30
|
+
|
31
|
+
### Fixed
|
32
|
+
- Fixed `gemspec` to allow newer version of `carrierwave` gem (thanks @edenvicary, see #12)
|
33
|
+
- Fixed `uninitialized constant CarrierWave::Mount::Mounter` (thanks @thanksoni7uka, see #11 and #12)
|
34
|
+
|
35
|
+
<!-- CHANGELOG started after version 2.0.1 -->
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,21 +1,81 @@
|
|
1
1
|
## CarrierWave for Neo4j
|
2
2
|
|
3
|
-
This gem adds support for Neo4j 3.0+ to CarrierWave
|
3
|
+
This gem adds support for Neo4j 3.0+ (neo4j.rb 9.6.0+) to CarrierWave 2.1.0+, see the CarrierWave documentation for more detailed usage instructions.
|
4
4
|
|
5
5
|
### Installation Instructions
|
6
6
|
|
7
7
|
Add to your Gemfile:
|
8
8
|
|
9
9
|
```ruby
|
10
|
-
gem 'carrierwave-neo4j',
|
10
|
+
gem 'carrierwave-neo4j', '~> 3.0', require: 'carrierwave/neo4j'
|
11
11
|
```
|
12
|
-
|
12
|
+
|
13
|
+
You can see example usage in `spec/neo4j_realistic_spec.rb` but in brief, you can use it like this:
|
13
14
|
|
14
15
|
```ruby
|
16
|
+
class AttachmentUploader < CarrierWave::Uploader::Base
|
17
|
+
storage :file
|
18
|
+
|
19
|
+
def store_dir
|
20
|
+
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
15
24
|
class Asset
|
16
25
|
include Neo4j::ActiveNode
|
17
26
|
|
18
27
|
property :attachment, type: String
|
19
28
|
mount_uploader :attachment, AttachmentUploader
|
20
29
|
end
|
21
|
-
```
|
30
|
+
```
|
31
|
+
|
32
|
+
If you want image manipulation, you will need to install ImageMagick
|
33
|
+
|
34
|
+
On Ubuntu:
|
35
|
+
|
36
|
+
```sh
|
37
|
+
sudo apt-get install imagemagick --fix-missing
|
38
|
+
```
|
39
|
+
|
40
|
+
On macOS:
|
41
|
+
|
42
|
+
```sh
|
43
|
+
brew install imagemagick
|
44
|
+
```
|
45
|
+
|
46
|
+
### Development
|
47
|
+
|
48
|
+
```sh
|
49
|
+
bundle install
|
50
|
+
rake neo4j:install[community-latest,test]
|
51
|
+
rake neo4j:start[test]
|
52
|
+
rake spec
|
53
|
+
```
|
54
|
+
|
55
|
+
### Troubleshooting
|
56
|
+
|
57
|
+
#### Files are nil
|
58
|
+
|
59
|
+
If you aren't getting your files back after querying a record from Neo4j, be aware that this will only happen automatically for the `Model#find` method. For all other finders (`#all`, `#first`, `#find_by`, `#find_by_*`, `#find_by_*!`, `#last`) you will need to force a reload so the model sees the file. For example:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
users = User.all
|
63
|
+
users.each(&:reload_from_database!)
|
64
|
+
```
|
65
|
+
|
66
|
+
Sorry, this sucks. But this is a limitation of Neo4j.rb as these other finders don't fire any callbacks.
|
67
|
+
|
68
|
+
#### binstubs (particularly `bin/rspec`) seem broken
|
69
|
+
|
70
|
+
If you're getting some infinite recursion when you run the specs that ultimately results in an error like:
|
71
|
+
|
72
|
+
```
|
73
|
+
`ensure in require': CRITICAL: RUBYGEMS_ACTIVATION_MONITOR.owned?: before false -> after true (RuntimeError)
|
74
|
+
```
|
75
|
+
|
76
|
+
You may want to try:
|
77
|
+
|
78
|
+
```sh
|
79
|
+
rm .bundle/config
|
80
|
+
bundle install
|
81
|
+
```
|
data/Rakefile
CHANGED
data/carrierwave-neo4j.gemspec
CHANGED
@@ -7,19 +7,21 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = CarrierWave::Neo4j::VERSION
|
8
8
|
s.authors = ["Rodrigo Navarro"]
|
9
9
|
s.email = ["navarro@manapot.com.br"]
|
10
|
-
s.homepage = "https://github.com/
|
10
|
+
s.homepage = "https://github.com/neo4jrb/carrierwave-neo4j"
|
11
11
|
s.summary = %q{Neo4j support for Carrierwave}
|
12
12
|
s.description = %q{Neo4j support for Carrierwave}
|
13
13
|
|
14
|
-
s.rubyforge_project = "carrierwave_neo4j"
|
15
|
-
|
16
14
|
s.files = `git ls-files`.split("\n")
|
17
15
|
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
18
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
17
|
s.require_paths = ["lib"]
|
20
18
|
|
21
|
-
s.add_dependency("activesupport", ">=
|
22
|
-
s.add_dependency("neo4j", "
|
23
|
-
s.add_dependency("carrierwave", "
|
24
|
-
s.add_development_dependency("rspec", "~>
|
19
|
+
s.add_dependency("activesupport", ">= 6.0" )
|
20
|
+
s.add_dependency("neo4j", "~> 9.6.0")
|
21
|
+
s.add_dependency("carrierwave", ">= 2.1")
|
22
|
+
s.add_development_dependency("rspec", "~> 3.0")
|
23
|
+
s.add_development_dependency("rspec-its")
|
24
|
+
s.add_development_dependency("webmock")
|
25
|
+
s.add_development_dependency("neo4j-rake_tasks")
|
26
|
+
s.add_development_dependency("rake")
|
25
27
|
end
|
data/lib/carrierwave/neo4j.rb
CHANGED
@@ -5,71 +5,207 @@ require "carrierwave/validations/active_model"
|
|
5
5
|
require "carrierwave/neo4j/uploader_converter"
|
6
6
|
require "active_support/concern"
|
7
7
|
|
8
|
+
######
|
9
|
+
# This file attempts to maintain symmetry with:
|
10
|
+
# https://github.com/carrierwaveuploader/carrierwave/blob/master/lib/carrierwave/orm/activerecord.rb
|
11
|
+
#
|
12
|
+
# Behaviours linked to callbacks (ex. `after_save :"store_#{column}!"`) belong to:
|
13
|
+
# https://github.com/carrierwaveuploader/carrierwave/blob/master/lib/carrierwave/mount.rb
|
14
|
+
# ...which is mixed into Model classes.
|
15
|
+
######
|
8
16
|
module CarrierWave
|
9
17
|
module Neo4j
|
10
|
-
extend ActiveSupport::Concern
|
11
18
|
|
19
|
+
# this class methods junk is necessary because ActiveNode is implemented as
|
20
|
+
# a model instead of a class for god-knows-what-reason.
|
21
|
+
extend ActiveSupport::Concern
|
12
22
|
module ClassMethods
|
23
|
+
|
13
24
|
include CarrierWave::Mount
|
25
|
+
|
14
26
|
##
|
15
27
|
# See +CarrierWave::Mount#mount_uploader+ for documentation
|
16
28
|
#
|
17
|
-
def mount_uploader(column, uploader
|
29
|
+
def mount_uploader(column, uploader=nil, options={}, &block)
|
18
30
|
super
|
19
31
|
|
32
|
+
mod = Module.new
|
33
|
+
prepend mod
|
34
|
+
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
|
35
|
+
def remote_#{column}_url=(url)
|
36
|
+
column = _mounter(:#{column}).serialization_column
|
37
|
+
__send__(:"\#{column}_will_change!")
|
38
|
+
super
|
39
|
+
end
|
40
|
+
RUBY
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# See +CarrierWave::Mount#mount_uploaders+ for documentation
|
45
|
+
#
|
46
|
+
def mount_uploaders(column, uploader=nil, options={}, &block)
|
47
|
+
super
|
48
|
+
|
49
|
+
mod = Module.new
|
50
|
+
prepend mod
|
51
|
+
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
|
52
|
+
def remote_#{column}_urls=(url)
|
53
|
+
column = _mounter(:#{column}).serialization_column
|
54
|
+
__send__(:"\#{column}_will_change!")
|
55
|
+
super
|
56
|
+
end
|
57
|
+
RUBY
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_reload_callback(method)
|
61
|
+
@_reload_callbacks = [] unless @_reload_callbacks
|
62
|
+
@_reload_callbacks << method unless @_reload_callbacks.include?(method)
|
63
|
+
end
|
64
|
+
|
65
|
+
def reload_callbacks
|
66
|
+
@_reload_callbacks
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def mount_base(column, uploader=nil, options={}, &block)
|
72
|
+
super
|
73
|
+
|
74
|
+
# this seems necessary to prevent the _identifier from including
|
75
|
+
# the entire path ('img.jpg' vs. '/uploads/user/image/img.jpg')
|
20
76
|
serialize column, ::CarrierWave::Uploader::Base
|
21
77
|
|
22
78
|
include CarrierWave::Validations::ActiveModel
|
23
79
|
|
24
|
-
validates_integrity_of
|
80
|
+
validates_integrity_of column if uploader_option(column.to_sym, :validate_integrity)
|
25
81
|
validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
|
82
|
+
validates_download_of column if uploader_option(column.to_sym, :validate_download)
|
83
|
+
|
84
|
+
# carrierwave keeps a instance variable of @uploaders, cached at init time
|
85
|
+
# but at init time, the value of the column is not yet available
|
86
|
+
# so after init, the empty @uploaders cache must be invalidated
|
87
|
+
# it will reinitialized with the processed column value on first access
|
88
|
+
after_initialize :_set_uploaders_nil
|
26
89
|
|
27
|
-
after_save :"store_#{column}!"
|
28
90
|
before_save :"write_#{column}_identifier"
|
91
|
+
after_save :"store_#{column}!"
|
92
|
+
# this 'after_update' hook doesn't seem necessary, but please
|
93
|
+
# don't remove it just in case it ever becomes necessary:
|
94
|
+
after_update :"mark_remove_#{column}_false"
|
29
95
|
after_destroy :"remove_#{column}!"
|
96
|
+
after_find :"force_retrieve_#{column}"
|
97
|
+
|
98
|
+
add_reload_callback :"force_retrieve_#{column}"
|
99
|
+
|
100
|
+
# TRYING THIS OUT FROM MONGOID:
|
101
|
+
# TODO: copy the other mongoid adapter code over
|
102
|
+
# https://github.com/carrierwaveuploader/carrierwave-mongoid/blob/master/lib/carrierwave/mongoid.rb
|
103
|
+
before_update :"store_previous_changes_for_#{column}"
|
104
|
+
after_save :"remove_previously_stored_#{column}"
|
30
105
|
|
31
106
|
class_eval <<-RUBY, __FILE__, __LINE__+1
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
107
|
+
|
108
|
+
# def remote_#{column}_url=(url) is defined in 'mount_uploader'
|
109
|
+
|
110
|
+
def #{column}=(new_file)
|
111
|
+
column = _mounter(:#{column}).serialization_column
|
112
|
+
if !(new_file.blank? && __send__(:#{column}).blank?)
|
113
|
+
__send__(:"\#{column}_will_change!")
|
114
|
+
end
|
115
|
+
super
|
116
|
+
end
|
117
|
+
|
118
|
+
def remove_#{column}=(value)
|
119
|
+
column = _mounter(:#{column}).serialization_column
|
120
|
+
result = super
|
121
|
+
__send__(:"\#{column}_will_change!") if _mounter(:#{column}).remove?
|
122
|
+
result
|
123
|
+
end
|
124
|
+
|
125
|
+
def remove_#{column}!
|
126
|
+
self.remove_#{column} = true
|
127
|
+
write_#{column}_identifier
|
128
|
+
self.remove_#{column} = false
|
129
|
+
super
|
130
|
+
end
|
131
|
+
|
132
|
+
# Reset cached mounter on record reload
|
133
|
+
def reload(*)
|
134
|
+
_set_uploaders_nil
|
135
|
+
@_mounters = nil
|
136
|
+
super
|
137
|
+
end
|
138
|
+
|
139
|
+
# Reset cached mounter on record dup
|
140
|
+
def initialize_dup(other)
|
141
|
+
_set_uploaders_nil
|
142
|
+
@_mounters = nil
|
143
|
+
super
|
144
|
+
end
|
145
|
+
|
146
|
+
def _set_uploaders_nil
|
147
|
+
if @_mounters
|
148
|
+
@_mounters.each do |_, mounter|
|
149
|
+
mounter.instance_variable_set(:@uploaders, nil)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def _force_uploaders_reload
|
155
|
+
@_mounters.each do |_, mounter|
|
156
|
+
mounter.send(:uploaders)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# okay, this actually works:
|
161
|
+
def force_retrieve_#{column}
|
162
|
+
send(:#{column}).send(:retrieve_from_store!, #{column}_identifier)
|
65
163
|
end
|
66
|
-
|
67
|
-
|
164
|
+
|
165
|
+
# these produce an infinite loop, so... don't reintroduce them:
|
166
|
+
# alias_method :read_uploader, :read_attribute
|
167
|
+
# alias_method :write_uploader, :write_attribute
|
168
|
+
# public :read_uploader
|
169
|
+
# public :write_uploader
|
170
|
+
|
171
|
+
def read_uploader(name)
|
172
|
+
send(:attribute, name.to_s)
|
173
|
+
end
|
174
|
+
|
175
|
+
def write_uploader(name, value)
|
176
|
+
send(:attribute=, name.to_s, value)
|
177
|
+
end
|
178
|
+
|
179
|
+
def reload_from_database
|
180
|
+
if reloaded = self.class.load_entity(neo_id)
|
181
|
+
self.class.reload_callbacks.each { |m| reloaded.send(m) }
|
182
|
+
end
|
183
|
+
reloaded
|
184
|
+
end
|
185
|
+
|
186
|
+
def reload_from_database!
|
187
|
+
if reloaded = self.class.load_entity(neo_id)
|
188
|
+
send(:attributes=, reloaded.attributes)
|
189
|
+
self.class.reload_callbacks.each { |m| send(m) }
|
190
|
+
end
|
191
|
+
self
|
192
|
+
end
|
193
|
+
|
194
|
+
# MONGOID:
|
195
|
+
# CarrierWave 1.1 references ::ActiveRecord constant directly which
|
196
|
+
# will fail in projects without ActiveRecord. We need to overwrite this
|
197
|
+
# method to avoid it.
|
198
|
+
# See https://github.com/carrierwaveuploader/carrierwave/blob/07dc4d7bd7806ab4b963cf8acbad73d97cdfe74e/lib/carrierwave/mount.rb#L189
|
199
|
+
def store_previous_changes_for_#{column}
|
200
|
+
@_previous_changes_for_#{column} = changes[_mounter(:#{column}).serialization_column]
|
201
|
+
end
|
202
|
+
|
68
203
|
RUBY
|
69
204
|
end
|
70
|
-
end
|
71
205
|
|
206
|
+
|
207
|
+
end
|
72
208
|
end
|
73
209
|
end
|
74
210
|
|
75
|
-
Neo4j::ActiveNode.
|
211
|
+
Neo4j::ActiveNode.include CarrierWave::Neo4j
|
@@ -7,7 +7,11 @@ module CarrierWave::Neo4j
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def to_db(value)
|
10
|
-
value.
|
10
|
+
if value.is_a?(Array)
|
11
|
+
value.map(&:identifier)
|
12
|
+
else
|
13
|
+
value.identifier
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
17
|
def to_ruby(value)
|
@@ -18,9 +22,15 @@ module CarrierWave::Neo4j
|
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
+
def register_converter(mod)
|
26
|
+
mod::TypeConverters.send :include, CarrierWave::Neo4j::TypeConverters
|
27
|
+
end
|
25
28
|
|
26
|
-
|
29
|
+
major = Neo4j::VERSION.split('.').first.to_i
|
30
|
+
|
31
|
+
case major
|
32
|
+
when 1..2 then fail('Unsupported version of Neo4j gem. Please update it.')
|
33
|
+
when 3 then register_converter(Neo4j)
|
34
|
+
when 4 then register_converter(Neo4j::Shared)
|
35
|
+
when 5..Float::INFINITY then Neo4j::Shared::TypeConverters.register_converter(CarrierWave::Neo4j::TypeConverters::UploaderConverter)
|
36
|
+
end
|