softace / paperclip_database Goto Github PK
View Code? Open in Web Editor NEWdatabase storage for paperclip
License: Other
database storage for paperclip
License: Other
The README dictates to use this command:
rails generate paperclip_database_migration
That should be:
rails generate paperclip_database
The exists? method loads the whole row from the files table, including the file blob. This is very slow for us as the files data is encrypted. It would help to have exists? - or another method - using a more efficient query.
i want to get my data via rest api.
for this i get a json like this:
"avatar": {
"content": "/9j/4AAQSkZJRgAdBAQEAkACQAAD/4QBaRXhpZgAATU0AKgAAAAgABQMBAAUA\nAAABAAAASgMDAAEAAAABAAAAAFEQAAEAAAABAQAAAFERAAQAAAABAAAWJVES\nAAQAAAABAAAWJQAAAAAAAYagAACxj//bAEMAAgEBAgEBAgICAgICAgIDBQMD\nAwMDBgQEAwUHBgcHBwYHBwgJCwkICAoIBwcKCgoLDAwMDAcJDg8NDA4LDAwM\n/9sAQwECAgIDAwMGAwMGDAgHCAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM\nDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgAFQAUAwEiAAIRAQMRAf/E\nAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMF\nBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJ\nChYXGBk=\n",
"content_type": "image/jpg",
"filename": "test.jpg"
},
then i am getting this error:
Paperclip::AdapterRegistry::NoHandlerError in Api::V1::UsersController#create
No Handler found
so i use a function from this example http://paoloibarra.com/2014/09/27/Image-Upload-Using-Rails-API-And-Paperclip/ but it seems not to be working with paperclip_database
in my logs are following entries, but nothing is stored in the database. no other error... its just ignoring the avatar:
[paperclip] Database Storage Initalized.
[paperclip] Deleting files for avatar
[paperclip] Writing files for avatar
Rails v5.0.1 on Postgres 9.5.x:
/Users/preston/.rvm/gems/ruby-2.3.3/gems/paperclip_database-2.3.1/lib/paperclip/storage/database.rb:196:in `block in flush_writes'
/Users/preston/.rvm/gems/ruby-2.3.3/gems/paperclip_database-2.3.1/lib/paperclip/storage/database.rb:189:in `each'
/Users/preston/.rvm/gems/ruby-2.3.3/gems/paperclip_database-2.3.1/lib/paperclip/storage/database.rb:189:in `flush_writes'
/Users/preston/.rvm/gems/ruby-2.3.3/gems/paperclip-5.1.0/lib/paperclip/attachment.rb:244:in `save'
/Users/preston/.rvm/gems/ruby-2.3.3/gems/paperclip-5.1.0/lib/paperclip/has_attached_file.rb:92:in `block in add_active_record_callbacks'
/Users/preston/.rvm/gems/ruby-2.3.3/gems/activesupport-5.0.1/lib/active_support/callbacks.rb:396:in `instance_exec'
...
To get working on Heroku, I had to set the :path
in the call to has_attached_file
like so:
has_attached_file :avatar,
:styles => { :medium => '300x280>' },
:storage => :database,
:path => ':rails_root/public/system/:class/:attachment/:id_partition/:style/:filename'
It took me a little bit to work that out, as it wasn't really obvious what the issue was. The image would actually upload successfully, and the binary would appear in the image table - but the file_name and content_type properties would be empty so the image couldn't be retrieved via paperclip.
What's weird, is that ":rails_root/public/system/:class/:attachment/:id_partition/:style/:filename" is meant to be the default value for the :path
setting anyway according to the paperclip documentation.
Is this something that needs to be fixed in paperclip_database?
If not, maybe add a note about setting the :path
to the README?
I have a working app that uses papercip_database gem version 2.2.2.
I recently updated to version 2.3.1 and received the following error message:
ActionView::Template::Error (undefined method `const_defined?' for nil:NilClass)
I did not change my code, all I did was upgrade the gem. Anything I'm doing wrong?
I also tried testing it out in the console and received the same error message but pointing to your new code:
from ../gems/paperclip_database-2.3.1/lib/paperclip/storage/database.rb:98 in 'setup_paperclip_file_model'
I'm using rails 3.2.11, ruby 1.9.3, and paperclip 3.5.0
Please let me know if I need to provide additional information.
I didn't go deep trying to solve this by myself, but looks like with any image I throw at it, the upload gives me this error.
The stacktrace got lost already, but the exception was raised in "lib/active_record/connection_adapters/postgresql/oid/bytea.rb".
I was using ruby 2.0, Postgres & Rails 4.2.
I already started to switch to using S3, but thought I still want to report this. Storing images in the local database would been a perfect fit for this small application (tiny amoung of images, no long term data retention, security important).
I noticed big speed regression for generated #attachment getter. Here are benchmarks comparing paperclip_database version 2.2.2 and 2.3.1:
2.2.2
> puts Benchmark.measure { 10.times { MyModel.last.csv_report } }
0.020000 0.000000 0.020000 ( 0.027583)
2.3.1
> puts Benchmark.measure { 10.times { MyModel.last.csv_report } }
0.770000 0.100000 0.870000 ( 0.924550)
(I call ActiveRecord::Base.last method in benchmark because only first call to csv_report is slow)
Profiling shows that 98% of time is spent in Paperclip::Storage::Database#setup_attachment_class
method.
Here is its implementation:
def setup_attachment_class
instance.class.ancestors.each do |ancestor|
# Pick the top-most definition like
# Paperclip::AttachmentRegistry#definitions_for
names_for_ancestor = ancestor.attachment_definitions.keys rescue []
if names_for_ancestor.member?(name)
@attachment_class = ancestor
end
end
end
This method is doing something very very very nasty. It iterates over all ancestors (which in typical rails application returns collection with size above 70 elements) and it call attachment_definitions
method. Of course most of the elements don't have this method so for most of them there will be raise error. Raising and rescuing errors in ruby are relatively slow so they shouldn't be used for normal flow.
Here is some more usefull metrics:
ActiveRecord::Base.ancestors.size
=> 70
> puts Benchmark.measure { ActiveRecord::Base.ancestors.each { |ancestor| ancestor.attachment_definitions rescue [] } }
0.060000 0.010000 0.070000 ( 0.080427)
One call takes ~0.08s - this is huge! It would be better to check if ancestor respond to this method before calling it:
puts Benchmark.measure {
ActiveRecord::Base.ancestors.each do |ancestor|
next unless ancestor.respond_to?(:attachment_definitions)
# call ancestor.attachment_definitions
end
}
0.000000 0.000000 0.000000 ( 0.000169)
Also there is no need to call keys
method in setup_attachment_class
method. attachment_definitions
returns hash and you can call has_key?
method directly on hash without creating intermediate Arra (also Hash#has_key? has O(1) complexity and Array#member? O(N)).
I found very annoying to have to create special controller just to serve file. So I did little experiment and added middleware that intercepts asset request and serves it before any controller is being call.
Just wanna share my idea here, maybe someone develops something fun from this.
Link to my extension:
https://github.com/kubenstein/paperclip_database_attachments_responder
The ActiveModel version checker blows up for Rails 5. Should work just the same as Rails 4.
After adding the downloads_files_for in my controller I get the next error:
undefined method `downloads_files_for' for GroupsController:Class
Any ideas?
Thanks!
There is a similar error in paperclip, but even if I point my Gemfile at the paperclip git repo to pick up the latest code, I still get the above error from paperclip_database.
Throwing the following in my application.rb allows me to run the generator, at which point I don't need the monkeypatch anymore:
module PaperclipDatabase
module Generators
class MigrationGenerator
public :migration_file_name
end
end
end
Command:
rails generate paperclip_database:migration Licensee request_form_pdf
Stack trace below:
/Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/generators/actions/create_migration.rb:13:in `migration_file_name': protected method `migration_file_name' called for #<PaperclipDatabase::Generators::MigrationGenerator:0x007fd34f6e7538> (NoMethodError)
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/generators/actions/create_migration.rb:34:in `existing_migration'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/actions/empty_directory.rb:112:in `invoke_with_conflict_check'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/actions/create_file.rb:60:in `invoke!'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/actions.rb:94:in `action'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/generators/migration.rb:34:in `create_migration'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/generators/migration.rb:63:in `migration_template'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/paperclip_database-2.2.2/lib/generators/paperclip_database/migration/migration_generator.rb:21:in `generate_migration'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/command.rb:27:in `run'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/invocation.rb:126:in `invoke_command'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/invocation.rb:133:in `block in invoke_all'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/invocation.rb:133:in `each'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/invocation.rb:133:in `map'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/invocation.rb:133:in `invoke_all'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/group.rb:232:in `dispatch'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/thor-0.19.1/lib/thor/base.rb:440:in `start'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/generators.rb:157:in `invoke'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/commands/generate.rb:11:in `<top (required)>'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:247:in `require'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:247:in `block in require'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:232:in `load_dependency'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:247:in `require'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/commands/commands_tasks.rb:135:in `generate_or_destroy'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/commands/commands_tasks.rb:51:in `generate'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from /Users/tpowell/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/railties-4.1.1/lib/rails/commands.rb:17:in `<top (required)>'
I am wondering if we really need new table for each file in class? We can use only one table paperclip_database_files
which will be in polymorphic association with active record model. cleaner solution imho, what do you think?
Hello, thanks for your awesome gem
i want to share my problem when using your gem
FYI my rails app using rails 4.0.1
so the case is
rails generate paperclip_database:migration User avatar
and i got migration with table name
def self.up
create_table :user_avatars do |t|
rake db:migrate
[paperclip] Deleting files for avatars
[paperclip] Writing files for avatars
PG::UndefinedTable: ERROR: relation "avatars" does not exist
LINE 5: WHERE a.attrelid = '"avatars"'::regclass
^
: SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = '"avatarts"'::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum
(0.2ms) ROLLBACK
Completed 500 Internal Server Error in 270ms
and after several time, i got solutions with rename table name in migrations file to
def self.up
create_table :avatars do |t|
:)
Anyone else interested in having attachments versioned with paper_trail?
What would need to be done for this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.