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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5507ccab191bfca681514fde9d25ad62c56ff8ab
4
- data.tar.gz: b849d9e4f6b4b73c7e985454f6f09fc10235e9b5
2
+ SHA256:
3
+ metadata.gz: ee1ece089b8cbd55532f4c0cba7a7a19054b24edc86f81a077c5497c49f4c801
4
+ data.tar.gz: a8a1b8fb5355129bfb9fd41839b59bbeee38e5808d59cac0a21fcc7ee6291a55
5
5
  SHA512:
6
- metadata.gz: 0911192167258d8be9d4ecf37857dc056725627706c30b2d853c0b6d4e10b8c38cd9fe3d0d90e0b143cc2ef5a8656fe1f0220d1ccac7aa9eeaa0ece0a39cd3ac
7
- data.tar.gz: 4fd214ca10c2f7a0950156760d3bf7a25b45dc2b618026a27118184dc47a9603632e1ef577f4c78dccfc57256178ae103ee0137d3f16f1471cd1fad391b7878e
6
+ metadata.gz: f2adb7d1d88b7f225d2d89c4bdcae75ada1f4fa3edfc5679cbd0aa034c80d6738bc2990dc9a2527555ae92837edbf9f447fb0ed811c9da133d2613c88019dd45
7
+ data.tar.gz: e9168769c2f8e656c3e8e1046e5c7d5fbaaec1d53269525557fe50b3f4a77ba08aa0966529cd5835750b4fe57b7b7a85b5e58aea3ac145b151f93e6c451b9a97
data/.gitignore CHANGED
@@ -6,3 +6,6 @@ db/*
6
6
  .idea
7
7
 
8
8
  .ruby-version
9
+ spec/public/uploads/*
10
+ bin/
11
+
@@ -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
@@ -2,5 +2,3 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in carrierwave_neo4j.gemspec
4
4
  gemspec
5
-
6
- gem 'database_cleaner', github: 'dpisarewski/database_cleaner', branch: 'neo4j'
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, see the CarrierWave documentation for more detailed usage instructions.
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', require: 'carrierwave/neo4j', github: 'dpisarewski/carrierwave-neo4j'
10
+ gem 'carrierwave-neo4j', '~> 3.0', require: 'carrierwave/neo4j'
11
11
  ```
12
- Use it like this:
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
@@ -1 +1,12 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'neo4j/rake_tasks'
3
+
4
+ begin
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default => :spec
10
+ rescue LoadError
11
+ puts "RSpec not installed...?"
12
+ end
@@ -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/reu/carrierwave-neo4j"
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", ">= 3.0" )
22
- s.add_dependency("neo4j", ">= 1.1")
23
- s.add_dependency("carrierwave", "~> 0.5")
24
- s.add_development_dependency("rspec", "~> 2.0")
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
@@ -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 = nil, options = {}, &block)
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 column if uploader_option(column.to_sym, :validate_integrity)
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
- def #{column}=(new_file)
33
- column = _mounter(:#{column}).serialization_column
34
- send(:attribute_will_change!, :#{column})
35
- super
36
- end
37
-
38
- def remote_#{column}_url=(url)
39
- column = _mounter(:#{column}).serialization_column
40
- send(:attribute_will_change!, :#{column})
41
- super
42
- end
43
-
44
- def remove_#{column}!
45
- super
46
- write_uploader(_mounter(:#{column}).serialization_column, nil)
47
- end
48
-
49
- def _mounter(column)
50
- @_mounters ||= {}
51
- @_mounters[column] ||= CarrierWave::Mount::Mounter.new(self, column)
52
- end
53
-
54
- def read_uploader(name)
55
- send(:attribute, name.to_s)
56
- end
57
-
58
- def write_uploader(name, value)
59
- send(:attribute=, name.to_s, value)
60
- end
61
-
62
- def reload_from_database
63
- if reloaded = self.class.load_entity(neo_id)
64
- send(:attributes=, reloaded.attributes.reject{ |k,v| v.is_a?(::CarrierWave::Uploader::Base) })
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
- reloaded
67
- end
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.send :include, CarrierWave::Neo4j
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.identifier
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
- mod = case Neo4j::VERSION.split('.').first.to_i
22
- when 3 then Neo4j
23
- when 4 then Neo4j::Shared
24
- end
25
+ def register_converter(mod)
26
+ mod::TypeConverters.send :include, CarrierWave::Neo4j::TypeConverters
27
+ end
25
28
 
26
- mod::TypeConverters.send :include, CarrierWave::Neo4j::TypeConverters
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