带有 Neo4j 的 Carrierwave 不将图像关联保存到数据库
Carrierwave with Neo4j not saving image assocation to DB
Rails 4 应用程序与 neo4j 和 neo4j.rb gem using carrierwave-neo4j 将图像附加到报告对象。
2.0.0-p353 :001 > r = Report.find_by(name: 'my new report')
=> #<Report avatar: #<AvatarUploader:0x0000000643d950 @model=#<Report avatar: #<AvatarUploader:0x0000000643d950 ...>, created_at: Thu, 19 Nov 2015 14:25:58 +0000, created_by: nil, description: nil, embedJSON: nil, gridsize: nil, name: "my new report", tableau_link: nil, thumbnail_uri: nil, timestamp: nil, type: nil, updated_at: Thu, 19 Nov 2015 15:01:18 +0000, updated_by: nil>, @mounted_as=:avatar>, created_at: Thu, 19 Nov 2015 14:25:58 +0000, created_by: nil, description: nil, embedJSON: nil, gridsize: nil, name: "my new report", tableau_link: nil, thumbnail_uri: nil, timestamp: nil, type: nil, updated_at: Thu, 19 Nov 2015 15:01:18 +0000, updated_by: nil>
2.0.0-p353 :002 > File.open('app/assets/images/nd-gray.png') { |f| r.avatar = f }
=> #<File:app/assets/images/nd-gray.png (closed)>
2.0.0-p353 :003 > r.avatar.url
=> "/vagrant/fenrir/tmp/uploads/1447945541-17455-0224/nd-gray.png"
2.0.0-p353 :004 > r.save
=> true
2.0.0-p353 :005 > r.avatar.url
=> "/uploads/development/Report/nd-gray.png"
此时一切正常。但是当我尝试重新加载 Report 对象时,关联消失了,就像从未发生过一样。
2.0.0-p353 :006 > r = Report.find_by(name: 'my new report')
=> #<Report avatar: #<AvatarUploader:0x00000004205108 @model=#<Report avatar: #<AvatarUploader:0x00000004205108 ...>, created_at: Thu, 19 Nov 2015 14:25:58 +0000, created_by: nil, description: nil, embedJSON: nil, gridsize: nil, name: "my new report", tableau_link: nil, thumbnail_uri: nil, timestamp: nil, type: nil, updated_at: Thu, 19 Nov 2015 15:05:53 +0000, updated_by: nil>, @mounted_as=:avatar>, created_at: Thu, 19 Nov 2015 14:25:58 +0000, created_by: nil, description: nil, embedJSON: nil, gridsize: nil, name: "my new report", tableau_link: nil, thumbnail_uri: nil, timestamp: nil, type: nil, updated_at: Thu, 19 Nov 2015 15:05:53 +0000, updated_by: nil>
2.0.0-p353 :007 > r.avatar.url
=> nil
2.0.0-p353 :007 > r.avatar.path
=> nil
切换到 :aws upload 而不是 :file 可以很好地上传,但同样缺少关联。
这是我的载波 class 对象。
#app/uploaders/avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
# Choose what kind of storage to use for this uploader:
storage :file
# Override the directory where uploaded files will be stored.
def store_dir
"uploads/#{Rails.env}/#{model.class}/"
end
# Add a white list of extensions which are allowed to be uploaded.
def extension_white_list
%w(jpg jpeg gif png)
end
end
和载波初始化器
#config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.storage = :file
config.aws_bucket = ENV['S3_BUCKET_NAME']
config.aws_acl = 'private'
config.aws_credentials = {
access_key_id: ENV['S3_KEY'],
secret_access_key: ENV['S3_SECRET'],
region: ENV['S3_REGION'] # Required
}
# The maximum period for authenticated_urls is only 10 minutes.
# config.aws_authenticated_url_expiration = 60 * 60 * 24 * 7
# # Set custom options such as cache control to leverage browser caching
# config.aws_attributes = {
# expires: 7.days.from_now.httpdate,
# cache_control: 'max-age=60480'
# }
config.cache_dir = "#{Rails.root}/tmp/uploads/" # To let CarrierWave work on heroku
# config.fog_directory = ENV['S3_BUCKET_NAME']
#config.s3_access_policy = :public_read # Generate http:// urls. Defaults to :authenticated_read (https://)
#config.fog_host = "#{ENV['S3_ASSET_URL']}/#{ENV['S3_BUCKET_NAME']}"
end
最后,报表模型本身
#app/models/report.rb
class Report
include Neo4j::ActiveNode
searchkick word_start: [:name], autocomplete: [:name]
validates_presence_of :name
validates_uniqueness_of :name, case_sensitive: false
property :avatar, type: String
mount_uploader :avatar, AvatarUploader
def search_data
{
name: name,
description: description
}
end
property :name
property :description
property :tableau_link
property :type
property :thumbnail_uri
property :gridsize
property :timestamp
property :embedJSON
property :created_at
property :updated_at
property :created_by
property :updated_by
has_many :in, :terms
has_one :in, :office
def selectable_terms
@selectable_terms = []
self.terms.each do |t|
@selectable_terms << { id: t.id, text: t.name }
end
@selectable_terms.to_json
end
def update_terms(param_terms)
param_terms ||= []
term_instances = []
param_terms.each do |t|
term_instances << Term.find_by(name: t)
end
term_instances
end
def aggro_extro
embedJSON.present? ? JSON.parse(embedJSON) : Hash.new
end
end
我能想到的一个原因是我们使用 :name 字段作为我们的唯一标识符。也许 carrierwave 正在寻找 UUID?
另一种可能是carrierwave正在缓存关联。
我刚试了一下,好像有用。我猜你使用的是旧版本的 neo4j
/ neo4j-core
宝石,因为当我尝试使用你的模型时它指出你没有指定 type
选项.从版本 5.0.0
开始,这是必需的。您能否更新到 5.2.0
系列,看看是否能解决问题?另请注意,6.0.0
很快就会发布(候选版本已经发布)。
我要提到的另一件事是,您可能应该在模型中为 name
属性 指定一个索引。这在按名称查询时应该有所帮助。因为你正在做 validates_uniqueness_of
你甚至可能想要指定一个约束。该约束不会以不区分大小写的方式确保值是唯一的,但它会在数据库级别为您做一些唯一性约束。您仍然需要 validates_uniqueness_of
和 case_sensitive: false
。请参阅以下文档:
http://neo4jrb.readthedocs.org/en/5.2.x/ActiveNode.html#indexes
http://neo4jrb.readthedocs.org/en/5.2.x/ActiveNode.html#constraints
另请注意,约束会自动创建索引,因此您无需同时指定两者(事实上,在 6.0.0 中我们不再允许您这样做)。
我最终放弃了 Carrierwave 并选择 Paperclip. The gems we're using with paperclip are as follows for anyone else having trouble with getting image uploads to play nice with neo4j.rb. The connector gem for paperclip is the neo4j.rb team's paperclip-fork
gem 'rails', '4.0.2'
gem 'neo4j', '~> 4.1.1'
gem 'neo4jrb-paperclip', github: 'subvertallchris/neo4jrb-paperclip', require: 'neo4jrb_paperclip'
gem 'aws-sdk-v1'
新的报表模型-
class Report
include Neo4j::ActiveNode
include Neo4jrb::Paperclip
has_neo4jrb_attached_file :avatar,
storage: :s3,
s3_permissions: :private,
default_url: '/assets/images/reports-icon-white.svg',
s3_credentials:
Proc.new { |a| a.instance.s3_credentials }
validates_attachment_content_type :avatar,
content_type: ['image/jpg',
'image/jpeg',
'image/png',
'image/gif']
# Rather than rename our variables in our secrets file, just rename them here
def s3_credentials
{
bucket: ENV['S3_BUCKET_NAME'],
access_key_id: ENV['S3_KEY'],
secret_access_key: ENV['S3_SECRET']
}
end
Rails 4 应用程序与 neo4j 和 neo4j.rb gem using carrierwave-neo4j 将图像附加到报告对象。
2.0.0-p353 :001 > r = Report.find_by(name: 'my new report')
=> #<Report avatar: #<AvatarUploader:0x0000000643d950 @model=#<Report avatar: #<AvatarUploader:0x0000000643d950 ...>, created_at: Thu, 19 Nov 2015 14:25:58 +0000, created_by: nil, description: nil, embedJSON: nil, gridsize: nil, name: "my new report", tableau_link: nil, thumbnail_uri: nil, timestamp: nil, type: nil, updated_at: Thu, 19 Nov 2015 15:01:18 +0000, updated_by: nil>, @mounted_as=:avatar>, created_at: Thu, 19 Nov 2015 14:25:58 +0000, created_by: nil, description: nil, embedJSON: nil, gridsize: nil, name: "my new report", tableau_link: nil, thumbnail_uri: nil, timestamp: nil, type: nil, updated_at: Thu, 19 Nov 2015 15:01:18 +0000, updated_by: nil>
2.0.0-p353 :002 > File.open('app/assets/images/nd-gray.png') { |f| r.avatar = f }
=> #<File:app/assets/images/nd-gray.png (closed)>
2.0.0-p353 :003 > r.avatar.url
=> "/vagrant/fenrir/tmp/uploads/1447945541-17455-0224/nd-gray.png"
2.0.0-p353 :004 > r.save
=> true
2.0.0-p353 :005 > r.avatar.url
=> "/uploads/development/Report/nd-gray.png"
此时一切正常。但是当我尝试重新加载 Report 对象时,关联消失了,就像从未发生过一样。
2.0.0-p353 :006 > r = Report.find_by(name: 'my new report')
=> #<Report avatar: #<AvatarUploader:0x00000004205108 @model=#<Report avatar: #<AvatarUploader:0x00000004205108 ...>, created_at: Thu, 19 Nov 2015 14:25:58 +0000, created_by: nil, description: nil, embedJSON: nil, gridsize: nil, name: "my new report", tableau_link: nil, thumbnail_uri: nil, timestamp: nil, type: nil, updated_at: Thu, 19 Nov 2015 15:05:53 +0000, updated_by: nil>, @mounted_as=:avatar>, created_at: Thu, 19 Nov 2015 14:25:58 +0000, created_by: nil, description: nil, embedJSON: nil, gridsize: nil, name: "my new report", tableau_link: nil, thumbnail_uri: nil, timestamp: nil, type: nil, updated_at: Thu, 19 Nov 2015 15:05:53 +0000, updated_by: nil>
2.0.0-p353 :007 > r.avatar.url
=> nil
2.0.0-p353 :007 > r.avatar.path
=> nil
切换到 :aws upload 而不是 :file 可以很好地上传,但同样缺少关联。
这是我的载波 class 对象。
#app/uploaders/avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
# Choose what kind of storage to use for this uploader:
storage :file
# Override the directory where uploaded files will be stored.
def store_dir
"uploads/#{Rails.env}/#{model.class}/"
end
# Add a white list of extensions which are allowed to be uploaded.
def extension_white_list
%w(jpg jpeg gif png)
end
end
和载波初始化器
#config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.storage = :file
config.aws_bucket = ENV['S3_BUCKET_NAME']
config.aws_acl = 'private'
config.aws_credentials = {
access_key_id: ENV['S3_KEY'],
secret_access_key: ENV['S3_SECRET'],
region: ENV['S3_REGION'] # Required
}
# The maximum period for authenticated_urls is only 10 minutes.
# config.aws_authenticated_url_expiration = 60 * 60 * 24 * 7
# # Set custom options such as cache control to leverage browser caching
# config.aws_attributes = {
# expires: 7.days.from_now.httpdate,
# cache_control: 'max-age=60480'
# }
config.cache_dir = "#{Rails.root}/tmp/uploads/" # To let CarrierWave work on heroku
# config.fog_directory = ENV['S3_BUCKET_NAME']
#config.s3_access_policy = :public_read # Generate http:// urls. Defaults to :authenticated_read (https://)
#config.fog_host = "#{ENV['S3_ASSET_URL']}/#{ENV['S3_BUCKET_NAME']}"
end
最后,报表模型本身
#app/models/report.rb
class Report
include Neo4j::ActiveNode
searchkick word_start: [:name], autocomplete: [:name]
validates_presence_of :name
validates_uniqueness_of :name, case_sensitive: false
property :avatar, type: String
mount_uploader :avatar, AvatarUploader
def search_data
{
name: name,
description: description
}
end
property :name
property :description
property :tableau_link
property :type
property :thumbnail_uri
property :gridsize
property :timestamp
property :embedJSON
property :created_at
property :updated_at
property :created_by
property :updated_by
has_many :in, :terms
has_one :in, :office
def selectable_terms
@selectable_terms = []
self.terms.each do |t|
@selectable_terms << { id: t.id, text: t.name }
end
@selectable_terms.to_json
end
def update_terms(param_terms)
param_terms ||= []
term_instances = []
param_terms.each do |t|
term_instances << Term.find_by(name: t)
end
term_instances
end
def aggro_extro
embedJSON.present? ? JSON.parse(embedJSON) : Hash.new
end
end
我能想到的一个原因是我们使用 :name 字段作为我们的唯一标识符。也许 carrierwave 正在寻找 UUID?
另一种可能是carrierwave正在缓存关联。
我刚试了一下,好像有用。我猜你使用的是旧版本的 neo4j
/ neo4j-core
宝石,因为当我尝试使用你的模型时它指出你没有指定 type
选项.从版本 5.0.0
开始,这是必需的。您能否更新到 5.2.0
系列,看看是否能解决问题?另请注意,6.0.0
很快就会发布(候选版本已经发布)。
我要提到的另一件事是,您可能应该在模型中为 name
属性 指定一个索引。这在按名称查询时应该有所帮助。因为你正在做 validates_uniqueness_of
你甚至可能想要指定一个约束。该约束不会以不区分大小写的方式确保值是唯一的,但它会在数据库级别为您做一些唯一性约束。您仍然需要 validates_uniqueness_of
和 case_sensitive: false
。请参阅以下文档:
http://neo4jrb.readthedocs.org/en/5.2.x/ActiveNode.html#indexes http://neo4jrb.readthedocs.org/en/5.2.x/ActiveNode.html#constraints
另请注意,约束会自动创建索引,因此您无需同时指定两者(事实上,在 6.0.0 中我们不再允许您这样做)。
我最终放弃了 Carrierwave 并选择 Paperclip. The gems we're using with paperclip are as follows for anyone else having trouble with getting image uploads to play nice with neo4j.rb. The connector gem for paperclip is the neo4j.rb team's paperclip-fork
gem 'rails', '4.0.2'
gem 'neo4j', '~> 4.1.1'
gem 'neo4jrb-paperclip', github: 'subvertallchris/neo4jrb-paperclip', require: 'neo4jrb_paperclip'
gem 'aws-sdk-v1'
新的报表模型-
class Report
include Neo4j::ActiveNode
include Neo4jrb::Paperclip
has_neo4jrb_attached_file :avatar,
storage: :s3,
s3_permissions: :private,
default_url: '/assets/images/reports-icon-white.svg',
s3_credentials:
Proc.new { |a| a.instance.s3_credentials }
validates_attachment_content_type :avatar,
content_type: ['image/jpg',
'image/jpeg',
'image/png',
'image/gif']
# Rather than rename our variables in our secrets file, just rename them here
def s3_credentials
{
bucket: ENV['S3_BUCKET_NAME'],
access_key_id: ENV['S3_KEY'],
secret_access_key: ENV['S3_SECRET']
}
end