Last active
November 21, 2021 22:00
-
-
Save fernandes/31c56b5aa1841643958031dc24c6a86b to your computer and use it in GitHub Desktop.
[Crystal Lang] Lucky Framework + Shrine File Uploader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
crystal: 0.34.0 | |
dependencies: | |
lucky: | |
github: luckyframework/lucky | |
version: ~> 0.21 | |
shrine: | |
github: jetrockets/shrine.cr | |
version: ~> 0.8 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "shrine" | |
Shrine.configure do |config| | |
config.storages["cache"] = Shrine::Storage::FileSystem.new("uploads", prefix: "cache") | |
config.storages["store"] = Shrine::Storage::FileSystem.new("uploads") | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# db/migrations/20200614172421_create_file_imports.cr | |
class CreateFileImports::V20200614172421 < Avram::Migrator::Migration::V1 | |
def migrate | |
# Learn about migrations at: https://luckyframework.org/guides/database/migrations | |
create table_for(FileImport) do | |
primary_key id : Int64 | |
add_timestamps | |
add asset_data : JSON::Any? | |
add_belongs_to post : Post, on_delete: :cascade | |
end | |
end | |
def rollback | |
drop table_for(FileImport) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# src/shards.cr | |
# (at the bottom) | |
require "shrine" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# given our `post` example, param_key will be `post` | |
file = params.nested_file?(:param_key)["image_attribute"]? | |
if file | |
# file.name | |
# "param_key:image_attribute" | |
# file.tempfile | |
#<File:/var/folders/41/g51hx5q90xqgk7wz9qv6738c0000gn/T/.3uQb3Bparam_key:image_attribute (closed)> | |
SaveFileImport.create!(upload: file, post_id: post.id) | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# src/models/file_import.cr | |
class FileImport < BaseModel | |
table do | |
column asset_data : JSON::Any? | |
belongs_to post : Post | |
# Now `commentable` could be a `photo` or `video` | |
polymorphic imageable, associations: [:post] | |
end | |
def blob_path | |
if data = asset_data | |
"/imports/#{data["id"].to_s}" | |
else | |
"" | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# src/models/post.cr | |
class Post < BaseModel | |
table do | |
# ..other fields.. | |
has_many images : FileImport | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# src/operations/save_file_import.cr | |
class FileImport::AssetUploader < Shrine | |
def generate_location(io : IO | UploadedFile, metadata, context, **options) | |
name = super(io, metadata, **options) | |
File.join("imports", name) | |
end | |
end | |
class SaveFileImport < FileImport::SaveOperation | |
permit_columns asset_data | |
needs upload : Lucky::UploadedFile | |
@asset_changed : Bool? = nil | |
property :asset_changed | |
before_save do | |
return true unless upload | |
return true if asset_changed == false | |
# do we need to create this new IO? | |
upload_io = IO::Memory.new(File.read(upload.path)) | |
asset_data.value = convert_shrine_uploader(FileImport::AssetUploader.cache(upload_io)) | |
@asset_changed = true | |
end | |
after_save move_to_store | |
def move_to_store(file_import : FileImport) | |
if asset_changed == true && asset_data.value | |
# do we need to create this new IO? | |
upload_io = IO::Memory.new(File.read(upload.path)) | |
asset_data.value = convert_shrine_uploader(FileImport::AssetUploader.store(upload_io, move: true, context: { model: file_import })) | |
@asset_changed = false | |
save! | |
end | |
true | |
end | |
def convert_shrine_uploader(uploader : Shrine::UploadedFile) : JSON::Any | |
JSON.parse(uploader.data.to_json) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# in some post show page | |
post.images.each do |image| | |
if image && (asset_data = image.asset_data) | |
img src: image.blob_path | |
else | |
text "No Image" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# in some post update (with form) | |
def render_post_form(op) | |
form_for Post::Update.with(@post.id), enctype: "multipart/form-data" do | |
# some fields... | |
file_input(op.image_attribute, attrs: [:required] | |
# ...some fields | |
submit "Update", data_disable_with: "Updating..." | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment