carrierwave-neo4j 2.0.0 → 3.0.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 +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
|