mul53 / activestorage-ipfs Goto Github PK
View Code? Open in Web Editor NEWThis gem extends the ActiveStorage::Service with an implementation for IPFS
License: MIT License
This gem extends the ActiveStorage::Service with an implementation for IPFS
License: MIT License
Hello, we are planning a project that would likely depend on this gem, and we would like to know if the developer team is in a position to continue the development or at least accept pull requests?
What is the situation on your side?
Thanks.
When using the direct upload feature pointed at localhost, you get a CORS error from IPFS, can you add a note to enable CORS on your node in the readme? The commands to enable it are:
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "GET", "POST"]'
When uploading the same file twice, rails throws a ActiveRecord::RecordNotUnique
error, I guess because the CID is the same and there's a uniqueness constraint on the key in the blob store table.
Perhaps it needs to attempt to find an existing record and use that in this case?
Started POST "/rails/active_storage/direct_uploads" for 127.0.0.1 at 2020-06-18 12:21:26 +0100
Processing by ActiveStorage::DirectUploadsController#create as JSON
Parameters: {"blob"=>{"key"=>"QmSyQ4e1KfMSdwP8A3Ks5HZMmVBXDuDXPqCd3kwwtqvVGp", "filename"=>"Photo on 25-05-2018 at 15.27.jpg", "content_type"=>"image/jpeg", "byte_size"=>135488, "checksum"=>"OAjxf4CriGSVkuIJTetm1g=="}, "direct_upload"=>{"blob"=>{"key"=>"QmSyQ4e1KfMSdwP8A3Ks5HZMmVBXDuDXPqCd3kwwtqvVGp", "filename"=>"Photo on 25-05-2018 at 15.27.jpg", "content_type"=>"image/jpeg", "byte_size"=>135488, "checksum"=>"OAjxf4CriGSVkuIJTetm1g=="}}}
(0.1ms) begin transaction
ActiveStorage::Blob Create (0.9ms) INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "byte_size", "checksum", "created_at") VALUES (?, ?, ?, ?, ?, ?) [["key", "QmSyQ4e1KfMSdwP8A3Ks5HZMmVBXDuDXPqCd3kwwtqvVGp"], ["filename", "Photo on 25-05-2018 at 15.27.jpg"], ["content_type", "image/jpeg"], ["byte_size", 135488], ["checksum", "OAjxf4CriGSVkuIJTetm1g=="], ["created_at", "2020-06-18 11:21:26.608964"]]
(0.1ms) rollback transaction
Completed 500 Internal Server Error in 8ms (ActiveRecord: 1.1ms | Allocations: 5346)
ActiveRecord::RecordNotUnique (SQLite3::ConstraintException: UNIQUE constraint failed: active_storage_blobs.key):
sqlite3 (1.4.2) lib/sqlite3/statement.rb:108:in `step'
sqlite3 (1.4.2) lib/sqlite3/statement.rb:108:in `block in each'
sqlite3 (1.4.2) lib/sqlite3/statement.rb:107:in `loop'
sqlite3 (1.4.2) lib/sqlite3/statement.rb:107:in `each'
activerecord (6.0.3.2) lib/active_record/connection_adapters/sqlite3/database_statements.rb:49:in `to_a'
activerecord (6.0.3.2) lib/active_record/connection_adapters/sqlite3/database_statements.rb:49:in `block (2 levels) in exec_query'
activesupport (6.0.3.2) lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
activesupport (6.0.3.2) lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
activesupport (6.0.3.2) lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'
activerecord (6.0.3.2) lib/active_record/connection_adapters/sqlite3/database_statements.rb:40:in `block in exec_query'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract_adapter.rb:722:in `block (2 levels) in log'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract_adapter.rb:721:in `block in log'
activesupport (6.0.3.2) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract_adapter.rb:712:in `log'
activerecord (6.0.3.2) lib/active_record/connection_adapters/sqlite3/database_statements.rb:39:in `exec_query'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/database_statements.rb:135:in `exec_insert'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/database_statements.rb:166:in `insert'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/query_cache.rb:22:in `insert'
activerecord (6.0.3.2) lib/active_record/persistence.rb:375:in `_insert_record'
activerecord (6.0.3.2) lib/active_record/persistence.rb:932:in `_create_record'
activerecord (6.0.3.2) lib/active_record/counter_cache.rb:166:in `_create_record'
activerecord (6.0.3.2) lib/active_record/locking/optimistic.rb:70:in `_create_record'
activerecord (6.0.3.2) lib/active_record/attribute_methods/dirty.rb:211:in `_create_record'
activerecord (6.0.3.2) lib/active_record/callbacks.rb:331:in `block in _create_record'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:135:in `run_callbacks'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:825:in `_run_create_callbacks'
activerecord (6.0.3.2) lib/active_record/callbacks.rb:331:in `_create_record'
activerecord (6.0.3.2) lib/active_record/timestamp.rb:110:in `_create_record'
activerecord (6.0.3.2) lib/active_record/persistence.rb:905:in `create_or_update'
activerecord (6.0.3.2) lib/active_record/callbacks.rb:327:in `block in create_or_update'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:135:in `run_callbacks'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:825:in `_run_save_callbacks'
activerecord (6.0.3.2) lib/active_record/callbacks.rb:327:in `create_or_update'
activerecord (6.0.3.2) lib/active_record/timestamp.rb:128:in `create_or_update'
activerecord (6.0.3.2) lib/active_record/persistence.rb:503:in `save!'
activerecord (6.0.3.2) lib/active_record/validations.rb:53:in `save!'
activerecord (6.0.3.2) lib/active_record/transactions.rb:318:in `block in save!'
activerecord (6.0.3.2) lib/active_record/transactions.rb:375:in `block in with_transaction_returning_status'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/database_statements.rb:280:in `block in transaction'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/transaction.rb:280:in `block in within_new_transaction'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
activesupport (6.0.3.2) lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/transaction.rb:278:in `within_new_transaction'
activerecord (6.0.3.2) lib/active_record/connection_adapters/abstract/database_statements.rb:280:in `transaction'
activerecord (6.0.3.2) lib/active_record/transactions.rb:212:in `transaction'
activerecord (6.0.3.2) lib/active_record/transactions.rb:366:in `with_transaction_returning_status'
activerecord (6.0.3.2) lib/active_record/transactions.rb:318:in `save!'
activerecord (6.0.3.2) lib/active_record/suppressor.rb:48:in `save!'
activerecord (6.0.3.2) lib/active_record/persistence.rb:55:in `create!'
activestorage-ipfs (a4b1b89a9330) lib/active_storage/service/ipfs_service.rb:13:in `create_before_direct_upload!'
activestorage (6.0.3.2) app/controllers/active_storage/direct_uploads_controller.rb:8:in `create'
actionpack (6.0.3.2) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (6.0.3.2) lib/abstract_controller/base.rb:195:in `process_action'
actionpack (6.0.3.2) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (6.0.3.2) lib/abstract_controller/callbacks.rb:42:in `block in process_action'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:135:in `run_callbacks'
actionpack (6.0.3.2) lib/abstract_controller/callbacks.rb:41:in `process_action'
actionpack (6.0.3.2) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (6.0.3.2) lib/action_controller/metal/instrumentation.rb:33:in `block in process_action'
activesupport (6.0.3.2) lib/active_support/notifications.rb:180:in `block in instrument'
activesupport (6.0.3.2) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activesupport (6.0.3.2) lib/active_support/notifications.rb:180:in `instrument'
actionpack (6.0.3.2) lib/action_controller/metal/instrumentation.rb:32:in `process_action'
actionpack (6.0.3.2) lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
activerecord (6.0.3.2) lib/active_record/railties/controller_runtime.rb:27:in `process_action'
actionpack (6.0.3.2) lib/abstract_controller/base.rb:136:in `process'
actionview (6.0.3.2) lib/action_view/rendering.rb:39:in `process'
actionpack (6.0.3.2) lib/action_controller/metal.rb:190:in `dispatch'
actionpack (6.0.3.2) lib/action_controller/metal.rb:254:in `dispatch'
actionpack (6.0.3.2) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
actionpack (6.0.3.2) lib/action_dispatch/routing/route_set.rb:33:in `serve'
actionpack (6.0.3.2) lib/action_dispatch/journey/router.rb:49:in `block in serve'
actionpack (6.0.3.2) lib/action_dispatch/journey/router.rb:32:in `each'
actionpack (6.0.3.2) lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack (6.0.3.2) lib/action_dispatch/routing/route_set.rb:834:in `call'
rack (2.2.3) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.3) lib/rack/etag.rb:27:in `call'
rack (2.2.3) lib/rack/conditional_get.rb:40:in `call'
rack (2.2.3) lib/rack/head.rb:12:in `call'
actionpack (6.0.3.2) lib/action_dispatch/http/content_security_policy.rb:18:in `call'
rack (2.2.3) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.3) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/cookies.rb:648:in `call'
activerecord (6.0.3.2) lib/active_record/migration.rb:567:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (6.0.3.2) lib/active_support/callbacks.rb:101:in `run_callbacks'
actionpack (6.0.3.2) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/debug_exceptions.rb:32:in `call'
web-console (4.0.3) lib/web_console/middleware.rb:132:in `call_app'
web-console (4.0.3) lib/web_console/middleware.rb:28:in `block in call'
web-console (4.0.3) lib/web_console/middleware.rb:17:in `catch'
web-console (4.0.3) lib/web_console/middleware.rb:17:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (6.0.3.2) lib/rails/rack/logger.rb:37:in `call_app'
railties (6.0.3.2) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (6.0.3.2) lib/active_support/tagged_logging.rb:80:in `block in tagged'
activesupport (6.0.3.2) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (6.0.3.2) lib/active_support/tagged_logging.rb:80:in `tagged'
railties (6.0.3.2) lib/rails/rack/logger.rb:26:in `call'
sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.2.3) lib/rack/method_override.rb:24:in `call'
rack (2.2.3) lib/rack/runtime.rb:22:in `call'
activesupport (6.0.3.2) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/static.rb:126:in `call'
rack (2.2.3) lib/rack/sendfile.rb:110:in `call'
actionpack (6.0.3.2) lib/action_dispatch/middleware/host_authorization.rb:82:in `call'
webpacker (4.2.2) lib/webpacker/dev_server_proxy.rb:23:in `perform_request'
rack-proxy (0.6.5) lib/rack/proxy.rb:57:in `call'
railties (6.0.3.2) lib/rails/engine.rb:527:in `call'
puma (4.3.5) lib/puma/configuration.rb:228:in `call'
puma (4.3.5) lib/puma/server.rb:713:in `handle_request'
puma (4.3.5) lib/puma/server.rb:472:in `process_client'
puma (4.3.5) lib/puma/server.rb:328:in `block in run'
puma (4.3.5) lib/puma/thread_pool.rb:134:in `block in spawn_thread'
Hi, I'm very interested in using this gem and probably send patches. So far I've found this:
class Site < ActiveRecord::Base
has_many_attached :files
end
Attaching a file twice throws a constraint error:
site = Site.create
site.files.attach io: File.open('/tmp/somefile.jpg'), filename: 'somefile.jpg')
site.files.attach io: File.open('/tmp/somefile.jpg'), filename: 'somefile.jpg')
=> ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: active_storage_attachments.record_type, active_storage_attachments.record_id, active_storage_attachments.name, active_storage_attachments.blob_id
Should IpfsService
catch duplicate Attachment
s and remove them? Also getting the last Attachment
without a query feels weird, wouldn't it be better to change it to something like Attachment.find_by(blob: new_blob)
?
I'll prepare a PR after discussing, thanks!
I was checking the direct uploads feature, from what I understand the file is going to be uploaded directly to the IPFS API, but this needs to be the uploaders local node or otherwise an IPFS node that's open to everyone, right?
Wouldn't it be better to generate an adhoc URL like DiskService, receive the file and internally upload it to the server's IPFS node that can be local or anywhere else, but not publicly open?
If you're interested I can write a patch, and I think this will remove the need for monkey patching ActiveStorage::DirectUploadsController
and ActiveStorage::Blob
, unless there's a need for this use case.
wow I was very curious to find this Rails gem, I would like to know if you would have problems using it in Ruby 3.0 with Rails 6.1.1, since I'm starting to use them as an experiment.
Anyway, I've just created a fork in case I have problems and see if I can use it. I really liked this gem
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.